วิธีที่ 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: วนซ้ำสองไฟล์
คุณสามารถวางคำสั่งที่ซับซ้อนตามที่คุณต้องการในเงื่อนไขของลูป while หากคุณใส่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
ตามข้างต้น ระวังพื้นที่ที่จำเป็นระหว่าง<
โอเปอเรเตอร์การเปลี่ยนเส้นทางและ<(
คำสั่งที่เริ่มต้น susbtitution
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
diff
ถ้าไม่ได้ดังนั้นเครื่องมือที่มีประสิทธิภาพอยู่แล้วที่จะเปรียบเทียบไฟล์เช่น