我对以下情况感到厌烦。
我有一个文件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中读取。但我觉得我可能会接近这个 - 谁知道。
帮助!
答案 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
)