如何在while循环中“读取”一个变量

53

如何在 while read line 中读取变量?

例如:

the_list=$(..code..)

while read line
do
        echo $line

done < $the_list

使用上面的代码会导致错误:

./copy.sh: line 25: $the_list: ambiguous redirect
4个回答

83

你可以写:

while IFS= read -r line
do
    echo "$line"
done <<< "$the_list"

请参见§3.6.7 "Here Strings" in the Bash Reference Manual

(为避免过多地操纵变量的内容,我还自作主张添加了一些双引号,并在read中添加了-rIFS=。)


2
IFS=会将IFS设置为空字符吗?为什么在这种情况下需要它? - doubleDown
6
@doubleDown: IFS=$IFS 设置为空字符串(因此它不包含任何字符)。在这种情况下,由于只有一个字段,它的唯一作用是防止删除行首的 IFS 字符。 (要了解我的意思,请比较 read foo <<< ' bar' ; echo "$foo"IFS= read foo <<< ' bar' ; echo "$foo"。) - ruakh

31

如果您不在其他地方使用该变量,甚至可以省略它:

while read line ; do
    echo $line
done < <( ... code ... )

27
你可以直接使用。
your_code | while read line;
do
    echo $line
done

如果您不介意在子shell中执行while循环(任何您修改的变量在done之后将不可见于父进程)。


这是一个旧回复。我对语句中的“...(在done之后修改的任何变量都不会在父级中可见)”部分很感兴趣。那么它们将如何变得“可见”?例如,以下示例echo "${NAMES/,/$'\n'}" |while read -r NAME ;do TMP=${NAME#*_} ;TMP2=${TMP%_*_*_*_*_*} ;OUTPUT+=${TMP2/$'\n'/,} ;done在循环后使用echo $OUTPUT不会返回任何内容。 - Nikos Alexandris
1
他们不会,就像我说的那样。你正在不同的进程中创建和/或修改变量。但是,变量并不是唯一的输出形式:循环仍然可以直接将输出打印到共享的stdout(事实上,这个示例就是这样做的),并且它仍然可以操作在子shell退出后仍然存在的文件。 - Useless
谢谢(再次)!以下是一个有些详细的例子,它完全按照我需要的方式工作:通过 while read -r NAME; do TMP=${NAME#*_} ;TMP2="${TMP%_*_*_*_*_*}" ;if [ -z $OUTPUT ] ;then OUTPUT+=${TMP2:-$TMP2} ;else OUTPUT+=${OUTPUT:+,$TMP2} ;fi ;done <<< ${NAMES//,/$'\n'*} 循环遍历 NAMES=x_myd11a1_lst_night_2019_01_01T01_30_00,x_myd21a1_lst_night_2019_01_01T01_30_00 ,得到 OUTPUT 变量 echo $OUTPUT: myd11a1_lst_night,myd21a1_lst_night - Nikos Alexandris

-5

脚本文件应该处于Linux模式。之前它是在dos模式下的。我使用dos2unix文件名进行了更改。

e.g.:

dos2unix sshcopy.sh

现在它对我来说可以工作了。


1
ruakh 提出的答案被提问者接受。这意味着问题与脚本文件格式无关。 - Simon MᶜKenzie

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接