方法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
如上所述进行处理。当心<
重定向操作符和<(
起始命令之间的必要空间。
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
循环调用来工作。它不必一定是一个函数,但是函数是最好的方法,既可以组织代码,又可以使该代码段被调用两次。在函数中,${!#}
是bash构造的一个实例,该实例的${!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
。