当他们可能缺少尾随换行符时,在bash中同时读取两个文件

时间:2018-02-06 18:16:52

标签: linux bash

我有两个文本文件,我试图同时逐行阅读。这些文件不一定具有相同的行数,并且当脚本到达任一文件的末尾时,脚本应该停止读取。我希望将此作为"纯粹的" bash尽可能。我发现的大部分解决方案都表明了以下形式:

while read -r f1 && read -r f2 <&3; do
    echo "$f1"
    echo "$f2"
done < file1 3<file2

但是,如果文件的最后一行没有换行符,则会失败。

如果我只是阅读一个文件,我会做类似的事情:

while IFS='' read -r line || [[ -n "$line" ]]; do
    echo "$line"
done < file1

但当我尝试通过以下方式扩展它来读取多个文件时:

while IFS='' read -r f1 || [[ -n "$f1" ]] && read -r f2 <&3 || [[ -n "$f2" ]]; do
    echo "$f1"
    echo "$f2"
done < file1 3<file2

while IFS='' read -r f1 && read -r f2 <&3 || [[ -n "$f1" || -n "$f2" ]]; do
    echo "$f1"
    echo "$f2"
done < file1 3<file2

我似乎无法使逻辑正确,并且循环不会在不读取最后一行的情况下终止或完成。

我可以使用以下方式获得所需的行为:

while true; do
    read -r f1 <&3 || if [[ -z "$f1" ]]; then break; fi;
    read -r f2 <&4 || if [[ -z "$f2" ]]; then break; fi;
    echo "$f1"
    echo "$f2"
done 3<file1 4<file2

然而,这似乎与正常(?)

相匹配
while ... read ...; do
     ... 
done

我看到的用于阅读文件的习语。

是否有更好的方法可以同时读取两个可能具有不同行数和最后一行不是换行符的文件?

我阅读文件的方式有哪些潜在的缺点?

1 个答案:

答案 0 :(得分:5)

您可以使用&&||{ }运算符进行分组来覆盖其优先级:

while { IFS= read -r f1 || [[ -n "$f1" ]]; } && { IFS= read -r f2 <&3 || [[ -n "$f2" ]]; }; do

一些注意事项:在这种情况下,您无法使用( )进行分组,因为这会强制其内容在子shell中运行,并且子shell中的变量read在子shell中不可用。此外,在每个;之前需要},因此shell可以告诉它不仅仅是最后一个命令的参数。最后,在每个 IFS=命令之前,您需要IFS=''(或等效read),因为作为命令前缀的赋值仅适用于该命令。