Metode 1: gunakan apa yang Anda ketahui
Karena Anda sudah tahu cara melompati satu file, Anda dapat menggabungkan file dan kemudian memproses file gabungan. Perintah tersebut paste
menggabungkan dua file baris demi baris. Ini menempatkan tab di antara garis yang berasal dari dua file, jadi solusi ini mengasumsikan bahwa tidak ada tab di nama file Anda. (Anda dapat mengubah pemisah tetapi Anda harus menemukan karakter yang tidak ada dalam nama file.)
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
Jika Anda ingin melewati baris kosong, Anda harus melakukannya di setiap file secara terpisah, karena paste
mungkin cocok dengan baris kosong dari satu file dengan baris non-kosong dari file lain. Anda dapat menggunakan grep
untuk menyaring garis yang tidak kosong.
paste -- <(grep '[^[:space:]]' "$list1.txt") <(grep '[^[:space:]]' "list2.txt") |
while IFS=$'\t' read -r file1 file2 rest; do
…
Perhatikan bahwa jika kedua file memiliki panjang yang berbeda, Anda akan mendapatkan yang kosong $file2
(terlepas dari daftar mana yang berakhir lebih dulu).
Metode 2: loop dua file
Anda dapat menempatkan perintah yang kompleks seperti yang Anda inginkan dalam kondisi loop sementara. Jika Anda meletakkan read file1 <&3 && read file2 <&4
maka loop akan berjalan selama kedua file memiliki satu baris untuk dibaca, yaitu sampai satu file habis.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3<list1..txt 4<list2.txt
Jika Anda ingin melompati garis kosong, ini sedikit lebih rumit, karena Anda harus melompati dua file secara mandiri. Cara mudah adalah memecah masalah menjadi dua bagian: lewati baris kosong dari satu file, dan proses baris yang tidak kosong. Salah satu metode untuk melewati garis kosong adalah dengan memproses grep
seperti di atas. Waspadai ruang yang diperlukan antara <
operator pengalihan dan <(
yang memulai susbtitusi perintah.
while read -u 3 -r file1 && read -u 4 -r file2; do
…
done 3< <(grep '[^[:space:]]' "$list1.txt") 4< <(grep '[^[:space:]]' "list2.txt")
Metode lain adalah menulis fungsi yang berperilaku seperti read
tetapi melompati garis kosong. Fungsi ini dapat bekerja dengan memanggil read
satu lingkaran. Itu tidak harus menjadi fungsi, tetapi fungsi adalah pendekatan terbaik, baik untuk mengatur kode Anda dan karena potongan kode itu perlu dipanggil dua kali. Dalam fungsinya, ${!#}
adalah turunan dari bash construct ${!VARIABLE}
yang mengevaluasi nilai dari variabel yang namanya adalah nilai VARIABLE
; di sini variabelnya adalah variabel khusus #
yang berisi jumlah parameter posisi, demikian ${!#}
juga parameter posisi terakhir.
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
.