while循环只在bash中的第一行文件上运行

时间:2017-12-19 18:51:14

标签: bash

我有一个while循环应该遍历文本文件,但在第一行停止,我无法弄清楚原因。我的代码如下。

while read hadoop_accounts; do
        if ! grep "no lock no remove"; then
                echo "${hadoop_accounts%%:*}"
                echo "${hadoop_accounts%%:*}" >> missing_no_lock_no_remove.txt
        fi
done < hadoop_accounts.txt

1 个答案:

答案 0 :(得分:3)

运行grep时没有显式重定向或要读取的文件,它会读取标准输入。标识符的全部。你的while read循环正在读取相同的标准输入。

因此,在grep消耗所有stdin的情况下,下一个read命令没有任何剩余消耗。

简单方法(性能更好)是对shell内部进行子字符串检查,而不是每行处理启动grep的新副本:

while IFS= read -r hadoop_accounts; do
        if ! [[ $hadoop_accounts = *"no lock no remove"* ]]; then
                echo "${hadoop_accounts%%:*}"
                echo "${hadoop_accounts%%:*}" >&3
        fi
done < hadoop_accounts.txt 3>> missing_no_lock_no_remove.txt

另请注意,我们只打开输出文件一次,而不是每次我们想要写一行时重新打开它。

如果确实希望每次只通过一行输入反复调用grep,那么可以执行此操作:

while IFS= read -r hadoop_accounts; do
        if ! grep "no lock no remove" <<<"$hadoop_accounts"; then
                echo "${hadoop_accounts%%:*}"
                echo "${hadoop_accounts%%:*}" >&3
        fi
done < hadoop_accounts.txt 3>> missing_no_lock_no_remove.txt

或者,甚至比上述任何一个更好,你可以在整个输入文件上一次运行grep并在循环中读取它的输出:

while IFS= read -r hadoop_accounts; do
  echo "${hadoop_accounts%%:*}"
  echo "${hadoop_accounts%%:*}" >&3
done < <(grep -v 'no lock no remove' <hadoop_accounts.txt) 3>>missing_flags.txt