Paralel olarak iki dosyanın satırından geçiş yapın [kapalı]


18

Yaptığım betiğin amacı iki dosya dizisini karşılaştırmak. Dosya adları, satır başına bir yol olmak üzere iki ayrı dosyada saklanır. Benim fikrim, while readher dosya adı listesi için bir tane olmak üzere iki döngüye sahip olmaktır , ancak iki döngüyü birlikte nasıl karıştırabilirim?

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

İki farklı listeden dosyaları aynı anda iki farklı döngüleri okurken karşılaştırmak gerekir ... Bu bile mümkün mü?


Bu senaryoyu bir meydan okuma kralı olarak yapmak istiyor musunuz? Değilse, dosyaları karşılaştırmak için güçlü araçlar zaten var diff.
lgeorget

" tür bir meydan okuma", özür dilerim
lgeorget

@lgeorget OP kullanıyor diff.
terdon

ah, iki listeden dosyalar . Yararsız yorumlar için özür dilerim ...
lgeorget

Yanıtlar:


20

İki döngüye ihtiyacınız yok; sadece bir döngüdeki iki dosyadan okumalısınız.

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 çok daha az kod teşekkürler! iki döngü için aynı anda boş bir satır istisnası nasıl ele alınır?
mkrouse

@mkrouse, daha önce orada bu $ sunucu değişkeni ile ne yaptığını bilmiyorum, ancak bir değişken üzerinde boş bir çizgi için test, ancak diğer aynı şeyi sadece ...
psusi

7

Yöntem 1: Bildiklerinizi Kullanın

Bir dosya üzerinde nasıl döngü yapılacağını zaten bildiğiniz için, dosyaları birleştirebilir ve daha sonra birleştirilmiş dosyaları işleyebilirsiniz. Komut pasteiki dosyayı satır satır birleştirir. İki dosyadan gelen satırlar arasına bir sekme koyar, bu nedenle bu çözüm dosya adlarınızda hiç sekme olmadığını varsayar. (Ayırıcıyı değiştirebilirsiniz, ancak dosya adında olmayan bir karakter bulmanız gerekir.)

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

Boş satırları atlamak istiyorsanız, her dosyada ayrı ayrı yapmanız gerekir, çünkü pastebir dosyadaki boş bir satırı başka bir dosyadaki boş olmayan bir satırla eşleştirebilir. grepBoş olmayan satırları filtrelemek için kullanabilirsiniz .

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

İki dosya farklı uzunluklara sahipse boş bir alan elde edeceğinizi unutmayın $file2(ilk önce hangi listenin sona erdiğine bakılmaksızın).

Yöntem 2: İki dosya üzerinde döngü

While döngüsü durumunda istediğiniz kadar karmaşık bir komut koyabilirsiniz. Eğer koyarsanız read file1 <&3 && read file2 <&4, döngü her iki dosya da okunacak bir çizgiye sahip olduğu sürece, yani bir dosya bitene kadar çalışır.

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

Boş satırları atlamak istiyorsanız, biraz daha karmaşıktır, çünkü iki dosyada atlamayı bağımsız olarak yapmanız gerekir. Kolay yol, sorunu iki bölüme ayırmaktır: boş satırları bir dosyadan atlamak ve boş olmayan satırları işlemek. Boş satırları atlamanın bir yolu grepyukarıdaki gibi işlem yapmaktır. Yeniden <yönlendirme operatörü ile <(komut susbtitüsyonu başlatan arasında gerekli boşluğa dikkat edin .

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

Başka bir yöntem de, readboş çizgiler atlayan ancak atlayan bir işlev yazmaktır . Bu işlev readbir döngü içinde çağrılarak çalışabilir . Bir işlev olmak zorunda değildir, ancak bir işlev hem kodunuzu düzenlemek için hem de bu kod parçasının iki kez çağrılması gerektiğinden en iyi yaklaşımdır. Fonksiyon olarak, ${!#}darbe yapısının bir örneğidir ${!VARIABLE}adı değişkenin değer öncelik değeri VARIABLE; burada değişken, #konumsal parametre sayısını içeren özel bir değişkendir , yani ${!#}son konumsal parametre de budur.

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

Okuma -useçeneğinin kullanımını seviyorum
Felipe Alvarez

1

Bir yaklaşım read -rasadece yerine kullanmak olacaktır read. filestoCompare.txtHer birinde dosya adlarının bulunduğu 2 sütunu varsayarsak, her read -raiki sütunu da aynı anda okur ve bunları bir diziye atar compareFile. Bu diziye daha sonra dizin 0 ilk dosya ve dizin 1 her whiledöngüde 2. dosya olacak şekilde erişilebilir .

Misal

Diyelim ki bu dosyam var: filestoCompare.txtve aşağıdakileri içeriyor:

file1 file2
file3 file4
file5 file6

Bu dosya üzerinden geçme komutu aşağıdaki gibi olacaktır:

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

2 dosya gerçekten aşağıdaki gibi ayrı dosyalarsa:

#list1
file1
file2
file3

#list2
file4
file5
file6

Komutla şu şekilde birleştirilebilirler paste:

$ paste list1 list2 > list1and2

List1and2 içeriği:

$ cat list1and2
file1   file4
file2   file5
file3   file6

Ancak bu girdi biçimi değildir: listeler iki farklı dosyadadır. Önce joinonlarý yapabilirsin .
Gilles 'SO- kötü olmayı bırak'

@Gilles - Bunun giriş biçimi olmadığını biliyorum, hatta "... totoTopare.txt dosyalarının her birinde dosya adları ile 2 sütun içerdiğini varsayarak ..." dediğine inanıyorum. Çekişmenizi anlıyorum ve katılmıyorum. OP bu soru hakkında yayınlandığından beri başka bir rehberlik sunmamıştır.
slm

@Gilles - paste2 dosyayı birleştirmek için komutun nasıl kullanılacağını gösteren bir örnek eklersem ne olur ? Bu sizi oy kullanmaz mı?
slm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.