সমান্তরালে দুটি ফাইলের লাইন ধরে [বন্ধ]


18

আমি যে স্ক্রিপ্টটি তৈরি করছি তার উদ্দেশ্য হ'ল দুটি সিরিজের ফাইলের তুলনা করা। ফাইলের নামগুলি নিজেরাই দুটি পৃথক ফাইলে সংরক্ষণ করা হয়, প্রতি লাইনে একটি পথ। আমার while readধারণামুলি ফাইলের নামের প্রতিটি তালিকার জন্য দুটি লুপ রয়েছে, তবে আমি কীভাবে দুটি লুপগুলিকে মিশ্রিত করতে পারি?

while read compareFile <&3; do     
 if [[ ! $server =~ [^[:space:]] ]] ; then  #empty line exception
    continue
 fi   
    echo "Comparing file - $compareFile"
 if diff "$compareFile" _(other file from loop?_) >/dev/null ; then
     echo Same
 else
      echo Different
 fi 
done 3</infanass/dev/admin/filestoCompare.txt

লুপগুলি পড়ার সময় আমার একই সময়ে দুটি পৃথক তালিকা থেকে দুটি ফাইলের তুলনা করতে সক্ষম হওয়া দরকার ... এটি কি সম্ভব?


আপনি কি এই স্ক্রিপ্টকে চ্যালেঞ্জের রাজা হিসাবে তৈরি করার পরিকল্পনা করছেন? যদি তা না হয় তবে শক্তিশালী সরঞ্জামগুলি ফাইলগুলির তুলনা করতে ইতিমধ্যে বিদ্যমান diff
দীর্ঘ

" ধরণের চ্যালেঞ্জ", দুঃখিত
10:43

@ লিগার্জেট ওপি ব্যবহার করছে diff
টেরডন

আহ, দুটি তালিকা থেকে ফাইল । অকেজো মন্তব্যগুলির জন্য দুঃখিত ...
দীর্ঘ

উত্তর:


20

আপনার দুটি লুপের দরকার নেই; আপনাকে কেবল একটি লুপে দুটি ফাইল থেকে পড়তে হবে।

while read compareFile1 <&3 && read compareFile2 <&4; do     
 if [[ ! $server =~ [^[:space:]] ]] ; then  #empty line exception
    continue
 fi   
    echo "Comparing file - $compareFile"
 if diff "$compareFile1" "$compareFile2" >/dev/null ; then
     echo Same
 else
      echo Different
 fi 
done 3</infanass/dev/admin/filestoCompare.txt 4<other_file

আরও অনেক কম কোড ধন্যবাদ! আমি কীভাবে একই সাথে দুটি লুপের জন্য একটি ফাঁকা লাইন ব্যতিক্রম পরিচালনা করব?
mkrouse

@ এমক্রাউজ, আমি জানি না যে আপনি আগে সেখানে $ সার্ভার ভেরিয়েবলটি দিয়ে কী করেছিলেন তবে আপনি যদি একটি ভেরিয়েবলের খালি লাইনের জন্য পরীক্ষা করেন তবে
অন্যটির জন্য

7

পদ্ধতি 1: আপনি যা জানেন তা ব্যবহার করুন

যেহেতু আপনি ইতিমধ্যে একটি ফাইলের উপর কীভাবে লুপ করবেন তা জানেন, আপনি ফাইলগুলি একত্রিত করতে পারেন এবং তারপরে সংযুক্ত ফাইলগুলি প্রক্রিয়া করতে পারেন। কমান্ডটি pasteলাইনে দুটি ফাইলের সাথে যুক্ত হয়। এটি দুটি ফাইল থেকে আগত রেখাগুলির মধ্যে একটি ট্যাব রাখে, সুতরাং এই সমাধানটি ধরে নেয় যে আপনার ফাইলের নামগুলিতে কোনও ট্যাব নেই। (আপনি বিভাজক পরিবর্তন করতে পারেন তবে আপনাকে এমন একটি অক্ষর খুঁজে পেতে হবে যা কোনও ফাইলের নামে উপস্থিত নেই))

paste -- "$list1.txt" "list2.txt" |
while IFS=$'\t' read -r file1 file2 rest; do
  diff -q -- "$file1" "$file2"
  case $? in
    0) status='same';;
    1) status='different';;
    *) status='ERROR';;
  esac
  echo "$status $file1 $file2"
done

আপনি যদি খালি লাইনগুলি এড়িয়ে যেতে চান তবে আপনার প্রতিটি ফাইলটিতে এটি আলাদাভাবে করা দরকার, যেহেতু pasteঅন্য ফাইল থেকে একটি ফাঁকা রেখার সাথে একটি ফাইলের ফাঁকা রেখার সাথে মিল থাকতে পারে। আপনি grepনন-ফাঁকা লাইনগুলি ফিল্টার করতে ব্যবহার করতে পারেন ।

paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
  

মনে রাখবেন যে দুটি ফাইলের দৈর্ঘ্য যদি আলাদা হয় তবে আপনি একটি খালি পাবেন $file2(কোন তালিকাটি প্রথমে শেষ হয়েছে তা নির্বিশেষে)।

পদ্ধতি 2: দুটি ফাইলের উপর লুপ করুন

উইন্ড লুপের অবস্থায় আপনি যেমন চান তেমন কমপ্লিট কমান্ড রাখতে পারেন। যদি আপনি রাখেন read file1 <&3 && read file2 <&4তবে লুপটি যতক্ষণ না উভয় ফাইলের পড়ার জন্য একটি লাইন থাকবে, অর্থাত্ একটি ফাইল শেষ না হওয়া অবধি চলবে।

while read -u 3 -r file1 && read -u 4 -r file2; do
  
done 3<list1..txt 4<list2.txt

আপনি যদি ফাঁকা রেখাগুলি ছাড়তে চান তবে এটি কিছুটা জটিল। কারণ আপনাকে দুটি ফাইলে স্বাধীনভাবে স্কিপিং করতে হবে। সহজ উপায় হ'ল সমস্যাটি দুটি ভাগে বিভক্ত করা: একটি ফাইল থেকে ফাঁকা লাইনগুলি এড়িয়ে চলুন এবং খালি ফাঁকা লাইনগুলি প্রক্রিয়া করুন। ফাঁকা লাইনগুলি এড়িয়ে যাওয়ার একটি পদ্ধতি grepউপরের মত প্রক্রিয়া করা । <পুনঃনির্দেশ অপারেটর এবং এটি <(একটি আদেশ কমান্ড শুরু করার মধ্যে প্রয়োজনীয় স্থানটির জন্য সন্ধান করুন ।

while read -u 3 -r file1 && read -u 4 -r file2; do
  
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")

আরেকটি পদ্ধতি হ'ল একটি ফাংশন লিখুন যা এর মতো আচরণ করে readতবে ফাঁকা লাইনগুলি এড়িয়ে যায়। এই ফাংশনটি readএকটি লুপে কল করে কাজ করতে পারে । এটি কোনও ফাংশন হওয়ার দরকার নেই, তবে আপনার কোডটি সংগঠিত করার জন্য একটি ফাংশন হ'ল সর্বোত্তম পন্থা এবং কারণ সেই অংশের কোডটি দু'বার কল করা প্রয়োজন। ফাংশনে, ${!#}বাশ কন্সট্রাক্টের একটি উদাহরণ ${!VARIABLE}যা ভেরিয়েবলের নামের মূল্য যা মূল্য হিসাবে মূল্যায়ন করে VARIABLE; এখানে ভ্যারিয়েবলটি হল একটি বিশেষ ভেরিয়েবল #যা পজিশনাল প্যারামিটারের সংখ্যা ধারণ করে, তাই ${!#}শেষ পজিশনাল প্যারামিটার।

function read_nonblank {
  while read "$@" &&
        [[ ${!#} !~ [^[:space:]] ]]
  do :; done
}
while read_nonblank -u 3 -r file1 && read_nonblank -u 4 -r file2; do
  
done 3<list1..txt 4<list2.txt

আমি পড়ার -uবিকল্পটি ব্যবহার করতে পছন্দ করি
ফিলিপ আলভারেজ

1

একটি পদ্ধতির ন্যায়বিচার read -raপরিবর্তে ব্যবহার করা হবে read। ধরে নেওয়া যাক filestoCompare.txtপ্রত্যেকটি ফাইলের নাম দিয়ে অন্তর্ভুক্ত 2 কলাম, read -ra, একই সময়ে উভয় কলাম পড়তে এবং তাদের একটি অ্যারের মধ্যে ধার্য হবে compareFile। এই অ্যারেটি তখন অ্যাক্সেস করা যায় যাতে সূচক 0 প্রথম ফাইল হয় এবং সূচক 1 whileলুপের মাধ্যমে প্রতিবার 2 য় ফাইল হয় ।

উদাহরণ

বলুন আমার কাছে এই ফাইলটি রয়েছে: filestoCompare.txtএবং এতে নিম্নলিখিতগুলি রয়েছে:

file1 file2
file3 file4
file5 file6

এই ফাইলটি দিয়ে যাওয়ার আদেশটি নীচে থাকবে:

$ while read -ra a ; do printf "%s\t%s\n" ${a[0]} ${a[1]}; done < filestoCompare.txt
file1   file2
file3   file4
file5   file6

যদি 2 টি ফাইল সত্যই পৃথক ফাইল থাকে তবে:

#list1
file1
file2
file3

#list2
file4
file5
file6

pasteকমান্ডের সাথে তাদের মত যোগ দেওয়া যেতে পারে :

$ paste list1 list2 > list1and2

তালিকা 1 এবং 2 এর সামগ্রীগুলি এখানে:

$ cat list1and2
file1   file4
file2   file5
file3   file6

তবে এটি ইনপুট ফর্ম্যাট নয়: তালিকাগুলি দুটি পৃথক ফাইলে রয়েছে। আপনি joinতাদের প্রথম করতে পারে ।
গিলস 13-22

@ গিলস - আমি জানি যে এটি ইনপুট ফর্ম্যাট নয়, আমি বিশ্বাস করি এমনকি আমি এটিও বলেছিলাম "... ফাইলস্টোরকম্পারে অনুমান করে। টেক্সটটিতে প্রতিটি ফাইলের নামের সাথে 2 টি কলাম রয়েছে ..."। আমি আপনার যুক্তি বুঝতে পেরেছি এবং একমত নই। ওপেন পোস্ট করার পর থেকে এই প্রশ্নে আর কোনও নির্দেশিকা সরবরাহ করেনি।
slm

@ গিলস - যদি আমি উদাহরণটিতে যুক্ত করি তবে কীভাবে paste2 ফাইলগুলিতে যোগদানের জন্য কমান্ডটি ব্যবহার করবেন ? এটি কি আপনাকে অনাবৃত হতে পারে?
slm
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.