在while循环内以bash读取输入


97

我有一个bash脚本,类似于以下内容,

cat filename | while read line
do
    read input;
    echo $input;
done

但这显然不能提供正确的输出,因为当我在while循环中读取时,由于可能的I / O重定向,它试图从文件文件名读取。

还有其他方法可以做到吗?


当您在bash中切换用户并在脚本中的切换用户下运行read命令时,
也会

Answers:



55

您可以通过单元3重定向常规的stdin,以将其保存在管道中:

{ cat notify-finished | while read line; do
    read -u 3 input
    echo "$input"
done; } 3<&0

顺便说一句,如果您确实使用cat这种方式,请用重定向替换它,事情变得更加简单:

while read line; do
    read -u 3 input
    echo "$input"
done 3<&0 <notify-finished

或者,您可以在该版本中交换stdin和unit 3-用unit 3读取文件,而不必管stdin:

while read line <&3; do
    # read & use stdin normally inside the loop
    read input
    echo "$input"
done 3<notify-finished

为什么第二个脚本挂起?
卡·博里奥尼

2
@LucaBorrione:您如何使用它?它是否在等待您输入信息(请注意,这read line是从notify-finished中读取的,但是如果您只是按照书面要求运行,则read -u 3 input是从控制台中读取)?
戈登·戴维森

4

尝试像这样更改循环:

for line in $(cat filename); do
    read input
    echo $input;
done

单元测试:

for line in $(cat /etc/passwd); do
    read input
    echo $input;
    echo "[$line]"
done

@ w2lame再次测试,将“ while”循环更改为“ for”循环-为我工作。尝试“性别-x”,看看错误来自哪里
dimba 2011年

4
不要使用猫,请参见Hai Vu的回答
Fredrik Pihl

+1。对于我的特定需求,这比其他建议更容易实现。
内森·华莱士

1
请参见Wooledge Wiki上的“ 不要阅读有关行”。另外,shellcheck.net警告SC2013
Charles Duffy

3

看起来您读了两次,不需要在while循环中读取。另外,您无需调用cat命令:

while read input
do
    echo $input
done < filename

4
OP的目标是使循环内部的读取来自用户,而外部的目标是从文件读取。因此,他们合法地希望从两个不同的来源获得两个不同的读物。从问题的文本(将内部read人员的行为描述为“不正确,因为它试图从文件中读取filename”)中可以清楚地看出这一点以及他们接受的答案。
Charles Duffy

1

我发现此参数-u与read一致。

“ -u 1”表示“从标准输入中读取”

while read -r newline; do
    ((i++))
    read -u 1 -p "Doing $i""th file, called $newline. Write your answer and press Enter!"
    echo "Processing $newline with $REPLY" # united input from two different read commands.
done <<< $(ls)

-6
echo "Enter the Programs you want to run:"
> ${PROGRAM_LIST}
while read PROGRAM_ENTRY
do
   if [ ! -s ${PROGRAM_ENTRY} ]
   then
      echo ${PROGRAM_ENTRY} >> ${PROGRAM_LIST}
   else
      break
   fi
done
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.