循环遍历bash中的文件中的行,而不使用stdin

时间:2013-11-01 13:21:04

标签: linux bash shell loops

我对以下情况感到厌烦。

我有一个文件list.txt,我希望逐行,循环,在bash中运行。 list.txt中的典型行包含空格。问题是循环包含“读取”命令。我想用bash编写这个循环而不是像perl这样的东西。我不能这样做: - (

以下是我通常会编写循环来逐行读取文件的方法:

while read p; do
  echo $p
  echo "Hit enter for the next one."
  read x
done < list.txt

这不起作用,因为当然“read x”将从list.txt而不是键盘读取。

这也不起作用:

for i in `cat list.txt`; do
    echo $i
    echo "Hit enter for the next one."
  read x
done

因为list.txt中的行有空格。

我有两个建议的解决方案,两个都很臭:

1)我可以编辑list.txt,并使用“THERE_SHOULD_BE_A_SPACE_HERE”全局替换所有空格。然后我可以在我的循环中使用像sed这样的东西用空格替换THERE_SHOULD_BE_A_SPACE_HERE并且我将全部设置好。我不喜欢这个愚蠢的原因,如果list.txt中的任何行包含短语THERE_SHOULD_BE_A_SPACE_HERE(因此恶意用户可能搞砸我),它将失败。

2)我可以使用带有stdin的while循环,然后在每个循环中我可以实际启动,例如一个新的终端,它不会受到原始shell中涉及stdin的事件的影响。我尝试了这个,我确实让它工作,但它很丑:我想把所有这些包装在一个shell脚本中,我不希望那个shell脚本随机打开新窗口。如果我能弄清楚如何以某种方式调用命令中的新shell并将命令提供给它而不向其提供stdin,那么什么会很好,以及可能以某种方式解决这个问题的答案,但我无法得到它工作。例如,这不起作用,我不知道为什么:

while read p; do 
  bash -c "echo $p; echo ""Press enter for the next one.""; read x;"; 
done < list.txt

这种尝试似乎失败了,因为“读取x”,尽管在某种程度上处于不同的shell中,仍然似乎从list.txt中读取。但我觉得我可能会接近这个 - 谁知道。

帮助!

3 个答案:

答案 0 :(得分:15)

您必须以不同的文件描述符

打开
while read p <&3; do
    echo "$p"
    echo 'Hit enter for the next one'
    read x
done 3< list.txt

更新:请忽略下面评论中冗长的讨论。它与问题或答案无关。

答案 1 :(得分:1)

我可能会计算文件中的行并使用例如迭代每个行。 SED。通过将条件更改为:while true;并使用 ctrl + c 退出读取,也可以从 stdin 无限读取。

line=0 lines=$(sed -n '$=' in.file)
while [ $line -lt $lines ]
do
    let line++
    sed -n "${line}p" in.file
    echo "Hit enter for the next ${line} of ${lines}."
    read -s x
done

AWK也是很好的工具。迭代输入的简单方法如下:

awk '{ print  $0; printf "%s", "Hit enter for the next"; getline < "-" }' file

答案 2 :(得分:0)

作为替代方案,您可以从stderr读取,默认情况下也连接到tty。以下还包括对该假设的测试:

(
tty -s <& 2|| exit 1
while read -r line; do
    echo "$line"
    echo 'Hit enter'
    read x <& 2
done < file
)