লুপ করার সময় দুটি ইনপুট ফাইল থেকে কীভাবে পড়বেন


27

আমি জানতে চেয়েছিলাম যে একবারে একটি লাইন লুপ করার সময় নেস্টযুক্ত দুটি ইনপুট ফাইল থেকে পড়ার কোনও উপায় আছে কিনা। উদাহরণস্বরূপ, ধরা যাক আমার কাছে দুটি ফাইল রয়েছে FileAএবং FileB

FileA:

[jaypal:~/Temp] cat filea
this is File A line1
this is File A line2
this is File A line3

FileB:

[jaypal:~/Temp] cat fileb
this is File B line1
this is File B line2
this is File B line3

বর্তমান নমুনা স্ক্রিপ্ট:

[jaypal:~/Temp] cat read.sh 
#!/bin/bash
while read lineA
    do echo $lineA 
    while read lineB
        do echo $lineB 
        done < fileb
done < filea

এক্সেকিউশন:

[jaypal:~/Temp] ./read.sh 
this is File A line1
this is File B line1
this is File B line2
this is File B line3
this is File A line2
this is File B line1
this is File B line2
this is File B line3
this is File A line3
this is File B line1
this is File B line2
this is File B line3

সমস্যা এবং পছন্দসই আউটপুট:

এটি ফাইলএ-র প্রতিটি লাইনের জন্য ফাইলবি-র উপর সম্পূর্ণভাবে লুপ করে। আমি চালিয়ে যাওয়া, বিরতি, প্রস্থান ব্যবহার করার চেষ্টা করেছি তবে সেগুলির কোনওটিই আমি সন্ধান করছি না এমন আউটপুট অর্জনের জন্য বোঝানো হচ্ছে। আমি স্ক্রিপ্টটি ফাইল এ থেকে কেবল একটি লাইন এবং তারপরে ফাইলবি থেকে একটি লাইন পড়তে এবং লুপ থেকে প্রস্থান এবং ফাইল এ এর ​​দ্বিতীয় লাইন এবং ফাইল বি এর দ্বিতীয় লাইনের সাথে চালিয়ে যেতে চাই - নীচের স্ক্রিপ্টের অনুরূপ কিছু -

[jaypal:~/Temp] cat read1.sh 
#!/bin/bash
count=1
while read lineA
    do echo $lineA 
        lineB=`sed -n "$count"p fileb`
        echo $lineB
        count=`expr $count + 1`
done < filea

[jaypal:~/Temp] ./read1.sh 
this is File A line1
this is File B line1
this is File A line2
this is File B line2
this is File A line3
this is File B line3

লুপ লুপ দিয়ে কি এটি অর্জন করা সম্ভব?


দ্বারা একটি মহান সমাধান @codaddict এখানে: stackoverflow.com/a/4011824/4095830 ->paste -d '\n' file1 file2
whoan

উত্তর:


32

যদি আপনি নিশ্চিতভাবেই জানেন যে কোনও অক্ষর প্রথম ফাইলে কখনই ঘটে না তবে আপনি পেস্টটি ব্যবহার করতে পারেন।

ডিফল্ট ডিলিমিটার ট্যাব ব্যবহার করে পেস্টের উদাহরণ:

paste file1 file2 | while IFS="$(printf '\t')" read -r f1 f2
do
  printf 'f1: %s\n' "$f1"
  printf 'f2: %s\n' "$f2"
done

পেস্ট ব্যবহারের উদাহরণ @:

paste -d@ file1 file2 | while IFS="@" read -r f1 f2
do
  printf 'f1: %s\n' "$f1"
  printf 'f2: %s\n' "$f2"
done

নোট করুন যে অক্ষরটি প্রথম ফাইলটিতে না হওয়ার গ্যারান্টিযুক্ত থাকলে এটি যথেষ্ট। এটি হ'ল শেষ ভেরিয়েবলটি পূরণ করার সময় readতা উপেক্ষা করা হবে IFS। এমনকি যদি@ দ্বিতীয় ফাইলটিতে ঘটে এটি বিভক্ত হবে না।

যুক্তিযুক্ত ক্লিনার কোডের জন্য কিছু বাশ বৈশিষ্ট্য ব্যবহার করে পেস্টের উদাহরণ:

while IFS=$'\t' read -r f1 f2
do
  printf 'f1: %s\n' "$f1"
  printf 'f2: %s\n' "$f2"
done < <(paste file1 file2)

ব্যাশ বৈশিষ্ট্য ব্যবহৃত: আনসিসি সি স্ট্রিং ( $'\t') এবং সাবসেল সমস্যাটির সময় লুপটি এড়াতে বিকল্প প্রতিস্থাপন ( <(...))

যদি আপনি নিশ্চিত না করতে পারেন যে কোনও অক্ষর উভয় ফাইলে কখনই ঘটে না তবে আপনি ফাইল বর্ণনাকারী ব্যবহার করতে পারেন ।

while true
do
  read -r f1 <&3 || break
  read -r f2 <&4 || break
  printf 'f1: %s\n' "$f1"
  printf 'f2: %s\n' "$f2"
done 3<file1 4<file2

বেশি পরীক্ষা করা হয়নি। খালি লাইনে বিরতি।

ফাইল বর্ণনাকারী 0, 1 এবং 2 নম্বর ইতিমধ্যে যথাক্রমে স্ট্ডিন, স্টডআউট এবং স্টডারারের জন্য ব্যবহৃত হয়। 3 বা তারপরের ফাইল বর্ণনাকারীরা (সাধারণত) বিনামূল্যে। বাশ ম্যানুয়াল 9 টির চেয়ে বেশি ফাইল বর্ণনাকারীদের ব্যবহার থেকে সতর্ক করে, কারণ সেগুলি "অভ্যন্তরীণভাবে ব্যবহৃত হয়"।

নোট করুন যে ওপেন ফাইল বর্ণনাকারীদের শেল ফাংশন এবং বাহ্যিক প্রোগ্রামগুলির উত্তরাধিকার সূত্রে প্রাপ্ত। একটি ওপেন ফাইল বিবরণকারী উত্তরাধিকার সূত্রে প্রাপ্ত ফাংশন এবং প্রোগ্রামগুলি ফাইল বিবরণকারী থেকে (এবং লিখতে) পড়তে পারে। কোনও ফাংশন বা বাহ্যিক প্রোগ্রাম কল করার আগে যে সমস্ত ফাইল বর্ণনাকারীর প্রয়োজন নেই সেগুলি বন্ধ করার জন্য আপনার যত্ন নেওয়া উচিত।

এখানে মেটা-ওয়ার্ক থেকে পৃথক প্রকৃত কাজ (মুদ্রণ) সমান্তরালভাবে দুটি সমান্তরালে দুটি ফাইল থেকে রেখার পঠন) উপরের একই প্রোগ্রামটি রয়েছে।

work() {
  printf 'f1: %s\n' "$1"
  printf 'f2: %s\n' "$2"
}

while true
do
  read -r f1 <&3 || break
  read -r f2 <&4 || break
  work "$f1" "$f2"
done 3<file1 4<file2

এখন আমরা ভান করি যে ওয়ার্ক কোড এবং কোডটির উপর আমাদের কোনও নিয়ন্ত্রণ নেই, যে কারণেই হোক না কেন ফাইল বর্ণনাকারী 3 থেকে পড়ার চেষ্টা করি।

unknowncode() {
  printf 'f1: %s\n' "$1"
  printf 'f2: %s\n' "$2"
  read -r yoink <&3 && printf 'yoink: %s\n' "$yoink"
}

while true
do
  read -r f1 <&3 || break
  read -r f2 <&4 || break
  unknowncode "$f1" "$f2"
done 3<file1 4<file2

এখানে একটি উদাহরণ আউটপুট। মনে রাখবেন যে প্রথম ফাইলের দ্বিতীয় লাইনটি লুপ থেকে "চুরি"।

f1: file1 line1
f2: file2 line1
yoink: file1 line2
f1: file1 line3
f2: file2 line2

বাহ্যিক কোডে কল করার আগে আপনার কীভাবে ফাইল বর্ণনাকারীদের বন্ধ করা উচিত (বা সেই বিষয়ে কোনও কোড)।

while true
do
  read -r f1 <&3 || break
  read -r f2 <&4 || break
  # this will close fd3 and fd4 before executing anycode
  anycode "$f1" "$f2" 3<&- 4<&-
  # note that fd3 and fd4 are still open in the loop
done 3<file1 4<file2

17

দুটি ফাইল বিভিন্ন ফাইল বর্ণনাকারীর উপর খুলুন । readআপনি যে ফাইলটি চাচ্ছেন তার সাথে অন্তর্নির্মিত ইনপুট পুনর্নির্দেশ করুন । বাশ / ksh / zsh এ, আপনি read -u 3পরিবর্তে লিখতে পারেন read <&3

while IFS= read -r lineA && IFS= read -r lineB <&3; do
  echo "$lineA"; echo "$lineB"
done <fileA 3<fileB

সংক্ষিপ্ততম ফাইলটি প্রক্রিয়া করার পরে এই স্নিপেটটি থামবে। লুপ চলাকালীন দুটি ফাইল আইএফএসে পড়ুন দেখুন - এই ক্ষেত্রে শূন্য ডিফার্ট পাওয়ার কোনও উপায় আছে কি? যদি আপনি উভয় ফাইলের সমাপ্তি অবধি প্রক্রিয়া চালিয়ে যেতে চান।

আরও দেখুন আপনি কখন অতিরিক্ত ফাইল বর্ণনাকারী ব্যবহার করবেন? ফাইল বর্ণনাকারী সম্পর্কিত অতিরিক্ত তথ্যের জন্য এবং আইএফএস = পড়ার সময় often আইএফএস = এর পরিবর্তে so যখন ব্যবহার করা হয়; পড়ার সময়..`? একটি ব্যাখ্যা জন্য IFS= read -r


ফাইল বর্ণনাকারীর অতিরিক্ত লিঙ্কগুলির জন্য @ গিলসকে ধন্যবাদ।
জয়পাল সিং

@ গিলস সম্ভবত আপনাকে ভুল বুঝেছি, তবে আমি লুপ প্রক্রিয়াটি দীর্ঘতম ফাইলটি সম্পূর্ণরূপে তৈরি করতে পারি না (যা আমার ক্ষেত্রে সর্বদা ফাইলএল), তাই আমি এটিকে একটি পৃথক প্রশ্নে পরিণত করেছি, হ'ল: লুপটি লেখার কি উপায় আছে? যে পার্থক্য ইনপুট এবং আউটপুট মধ্যে কোন পার্থক্য লক্ষ্য করে না? unix.stackexchange.com/questions/26780/… আমি যে নিকটতম পেলাম তা কেবল পার্থক্যের একটি লাইন সন্ধান করতে পার্থক্য ছিল।
ixtmixilix

3

আমি জানি আপনি শেল স্ক্রিপ্ট চান তবে আপনি pasteকমান্ডটি একবার দেখে নিতে পারেন ।


ধন্যবাদ @ লুটজকী pasteখুব সুন্দর।
জয়পাল সিং

2

নীচে কমান্ড চেষ্টা করুন:

paste -d '\n' inp1.txt inp2.txt > outfile.txt

0

বিকল্পভাবে, আমি মনে করি আপনি বাশের মানচিত্রের ফাইলটি কমান্ডটি ব্যবহার করে ফাইলের প্রতিটি লাইনকে অ্যারে [line_of_file_index] এ আবদ্ধ করে একটি অ্যারে ভেরিয়েবলে ফাইল স্লার্প করতে পারেন। তবে আমি নিশ্চিত নই যে এটি কেবল বাশ 3 উচ্চতর বা বাশ 4 এর জন্য কিনা।

http://wiki.bash-hackers.org/commands/builtin/mapfile

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.