在 bash 的 C 样式 for 循环中模拟“while IFS= read -r line”

Ser*_*nyy 6 command-line scripting bash ksh files

首先是这个问题的一些背景。这while IFS= read -r line; do ... done < input.txt是一种众所周知的结构,用于在 shell 脚本中逐行读取文件。但是一直在使用 c 风格的 for 循环(以防这里的一些用户不知道,它是and 中for((i=0;i<=$val;i++))do;...done使用的类型),我记得在类 C 语言中的 while 和 for 循环是可以互换的,并且可以模拟一个其他。所以我想出了一个模拟上面提到的结构的c风格的循环。bashkshwhile IFS= read -r line

for((i=1;;i++))
do 
    IFS= read -r line || break
    # do something with line here
done < input.txt
Run Code Online (Sandbox Code Playgroud)

我已经用多种类型的输入对其进行了测试 - 普通行、带有前导制表符/空格的行、不以结尾的行\n(这是read无法捕捉到最后一行的情况) - 在所有情况下这都可以正常工作与while循环方法相同。这在技术上也有一个带有i变量的“内置”行计数器。

所以,问题是:是否有任何理由(除了不可移植到除ksh和之外的其他外壳外bash)避免使用这种方法?是否有可能会失败的情况?虽然这很有效,但我想知道在开始在我自己的脚本中积极使用这种方法之前是否有任何我忽略的问题。

ilk*_*chu 5

有什么理由避免使用这种方法吗?

清晰,或缺乏它。

一个while循环while sometest ; do ...也可以写成

while :; do 
    if ! sometest; then
        break
    fi
    ...
Run Code Online (Sandbox Code Playgroud)

但我们不这样做(在 shell 中,或在 C 中),因为它将循环条件从人们习惯于寻找它的地方移开。您的构造类似:您将for (( ; ; ))构造的中间表达式留空。

当然你必须这样做,因为for (( ; ; ))在 shell 中只计算算术表达式,而不是像read. 尽管forwhile可以稍微轻松地用C转化,同样并不真正适用,因为这个壳:他们做不同的事情。

(我会说即使在 C 中,for循环的结构也暗示了计数循环,但当然它并不完全明确。)

至于这个:

这在技术上也有一个带有 i 变量的“内置”行计数器。

我不认为里面有任何内置的东西。您手动初始化行计数器,然后手动增加它。你可以用更传统的while循环做同样的事情

i=0
while IFS= read -r line; do 
    ... 
    let i++
done < input.txt
Run Code Online (Sandbox Code Playgroud)

(或者i=$((i + 1))更便携)