Metoda 1: użyj tego, co wiesz
Ponieważ wiesz już, jak zapętlić jeden plik, możesz połączyć pliki, a następnie przetworzyć połączone pliki. Polecenie paste
łączy dwa pliki linia po linii. Umieszcza tabulator między wierszami pochodzącymi z dwóch plików, więc to rozwiązanie zakłada, że w nazwach plików nie ma tabulatorów. (Możesz zmienić separator, ale musisz znaleźć znak, którego nie ma w nazwie pliku).
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
Jeśli chcesz pominąć puste linie, musisz to zrobić w każdym pliku osobno, ponieważ paste
może on pasować do pustej linii z jednego pliku z niepustą linią z innego pliku. Możesz użyć grep
do filtrowania niepustych linii.
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
Pamiętaj, że jeśli dwa pliki mają różne długości, otrzymasz pusty $file2
(niezależnie od tego, która lista kończy się jako pierwsza).
Metoda 2: zapętlenie dwóch plików
Możesz umieścić tak złożone polecenie, jak chcesz w warstwie pętli while. Jeśli wstawisz, read file1 <&3 && read file2 <&4
pętla będzie działać tak długo, jak oba pliki będą miały linię do odczytania, tj. Dopóki jeden plik się nie skończy.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
Jeśli chcesz pominąć puste linie, jest to trochę bardziej skomplikowane, ponieważ musisz wykonać pomijanie dwóch plików niezależnie. Prostym sposobem jest podzielenie problemu na dwie części: pominięcie pustych linii z jednego pliku i przetworzenie niepustych linii. Jedną z metod pomijania pustych linii jest przetworzenie grep
jak wyżej. Uważaj na niezbędną przestrzeń między <
operatorem przekierowania a operatorem <(
rozpoczynającym zawieszanie polecenia.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
Inną metodą jest napisanie funkcji, która zachowuje się tak, read
ale pomija puste linie. Ta funkcja może działać, wywołując read
pętlę. Nie musi to być funkcja, ale funkcja jest najlepszym podejściem, zarówno do uporządkowania kodu, jak i dlatego, że ten fragment kodu należy wywołać dwukrotnie. W funkcji ${!#}
jest instancja konstrukcji bash, ${!VARIABLE}
która ocenia wartość zmiennej, której nazwa jest wartością VARIABLE
; tutaj zmienna jest specjalną zmienną, #
która zawiera liczbę parametru pozycyjnego, podobnie ${!#}
jak ostatni parametr pozycyjny.
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
diff
.