समानांतर में दो फ़ाइलों की लाइनों के माध्यम से लूप [बंद]


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
लार्जेट

"एक तरह की चुनौती", क्षमा करें
lagorget

@ ऑलगॉरेट ओपी उपयोग कर रहा है diff
terdon

आह, दो सूचियों से फाइलें । बेकार टिप्पणियों के लिए क्षमा करें ...
lgeorget

जवाबों:


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

Thats बहुत कम कोड धन्यवाद बहुत! मैं एक ही समय में दो छोरों के लिए एक खाली लाइन अपवाद को कैसे संभाल सकता हूं?
mkrouse

@mkrouse, मुझे नहीं पता कि आप उस $ सर्वर चर के साथ पहले क्या कर रहे थे, लेकिन हालाँकि आप एक चर पर एक खाली लाइन के लिए परीक्षण करते हैं, आप बस दूसरे पर भी ऐसा ही करते हैं ...
psusi

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ऊपर के माध्यम से प्रक्रिया करना है। <पुनर्निर्देशन ऑपरेटर के बीच आवश्यक स्थान के लिए बाहर देखो और <(कि एक आदेश susbtocation शुरू होता है।

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सिर्फ के बजाय उपयोग करने के लिए होगा readfilestoCompare.txtप्रत्येक में फ़ाइल नामों के साथ सम्‍मिलित 2 कॉलमों को मानते हुए read -ra, एक ही समय में दोनों कॉलमों को पढ़ेंगे और उन्हें एक सरणी में असाइन करेंगे compareFile। इस सरणी को तब एक्सेस किया जा सकता है ताकि अनुक्रमणिका पहली फ़ाइल होगी और अनुक्रमणिका 1 whileलूप के माध्यम से हर बार दूसरी फ़ाइल होगी ।

उदाहरण

कहो कि मेरे पास यह फ़ाइल है: 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

यहाँ list1and2 की सामग्री है:

$ cat list1and2
file1   file4
file2   file5
file3   file6

लेकिन वह इनपुट प्रारूप नहीं है: सूची दो अलग-अलग फाइलों में हैं। आप joinउन्हें पहले कर सकते थे।
गिलेस एसओ- बुराई को रोकना '

@ गिल्स - मुझे पता है कि यह इनपुट प्रारूप नहीं है, मेरा मानना ​​है कि मैंने यहां तक ​​कहा कि "... filestoCompare.txt को मानते हुए प्रत्येक में फ़ाइल नाम के साथ 2 कॉलम सम्‍मिलित हैं ..."। मैं आपके विवाद को समझता हूं और असहमत नहीं हूं। ओपी ने इस प्रश्न पर कोई और मार्गदर्शन नहीं दिया है क्योंकि यह पोस्ट किया गया है।
स्लम

@ गिल्स - क्या होगा अगर मैं एक उदाहरण जोड़कर बताऊं pasteकि 2 फाइलों में शामिल होने के लिए कमांड का उपयोग कैसे करें? क्या यह आपको बिना सोचे समझे मिल जाएगा?
स्लम
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.