为了账号安全,请及时绑定邮箱和手机立即绑定

在while循环中修改的变量不会被记住。

在while循环中修改的变量不会被记住。

在while循环中修改的变量不会被记住。在下面的程序中,如果我设置了变量$foo中的值1。if语句,它的工作原理是在if语句之后记住它的值。但是,当我将相同的变量设置为if在一个while语句之后,它就被遗忘了。while循环。它的行为就像我在使用变量的某种拷贝$foo内部while循环和我只是在修改特定的副本。下面是一个完整的测试程序:#!/bin/bashset -eset -u foo=0bar="hello"  if [[ "$bar" == "hello" ]]then    foo=1    echo "Setting \$foo to 1: $foo"fiecho "Variable \$foo after if statement: $foo"   lines="first line\nsecond line\nthird line" echo -e $lines | while read linedo    if [[ "$line" == "second line" ]]    then    foo=2    echo "Variable \$foo updated to $foo inside if inside while loop"    fi    echo "Value of \$foo in while loop body: $foo"doneecho "Variable \$foo after while loop: $foo"# Output:# $ ./testbash.sh# Setting $foo to 1: 1# Variable $foo after if statement: 1# Value of $foo in while loop body: 1# Variable $foo updated to 2 inside if inside while loop# Value of $foo in while loop body: 2# Value of $foo in while loop body: 2# Variable $foo after while loop: 1# bash --version# GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)
查看完整描述

3 回答

?
慕桂英3389331

TA贡献2036条经验 获得超8个赞

echo -e $lines | while read line 
    ...done

这个while循环在子shell中执行。因此,一旦子shell退出,您对变量所做的任何更改都将不可用。

相反,您可以使用这里串在主外壳进程中重写while循环;仅echo -e $lines将在子shell中运行:

while read linedo
    if [[ "$line" == "second line" ]]
    then
        foo=2
        echo "Variable \$foo updated to $foo inside if inside while loop"
    fi
    echo "Value of \$foo in while loop body: $foo"done <<< "$(echo -e "$lines")"

你可以摆脱那些相当丑陋的人echo在上述字符串中,在赋值时立即展开反斜杠序列。lines。这个$'...'引用的形式可以在这里使用:

lines=$'first line\nsecond line\nthird line'while read line; do
    ...done <<< "$lines"


查看完整回答
反对 回复 2019-05-30
?
繁花如伊

TA贡献2012条经验 获得超12个赞

备选解决办法:

消去echo

while read line; do...done <<EOT
first line
second line
third line
EOT

在“这里是文档”中添加回显。

while read line; do...done <<EOT
$(echo -e $lines)EOT

echo背景:

coproc echo -e $lineswhile read -u ${COPROC[0]} line; do ...done

显式地重定向到文件句柄(请注意< <!):

exec 3< <(echo -e  $lines)while read -u 3 line; do...done

或者重定向到stdin:

while read line; do...done < <(echo -e  $lines)

一张是给你的chepner(消除echo):

arr=("first line" "second line" "third line");for((i=0;i<${#arr[*]};++i)) { line=${arr[i]}; ...}

变量$lines可以在不启动新的子shell的情况下转换为数组。人物\n必须转换为某个字符(例如,一个真正的新行字符),并使用IFS(内部字段分隔符)变量将字符串拆分为数组元素。可以这样做:

lines="first line\nsecond line\nthird line"echo "$lines"OIFS="$IFS"IFS=$'\n' arr=(${lines//\\n/$'\n'})
 # ConversionIFS="$OIFS"echo "${arr[@]}", Length: ${#arr[*]}set|grep ^arr

结果是

first line\nsecond line\nthird line
first line second line third line, Length: 3arr=([0]="first line" [1]="second line" [2]="third line")


查看完整回答
反对 回复 2019-05-30
?
慕丝7291255

TA贡献1859条经验 获得超6个赞

描述了管道创建的子shell中设置的变量的一般情况:

E4)如果我将命令的输出输送到read variable,为什么输出没有出现在$variable读取命令何时结束?

这与Unix进程之间的父-子关系有关。它影响在管道中运行的所有命令,而不仅仅是对read。例如,将命令的输出转换为while循环,反复调用read会导致同样的行为。

管道的每个元素,甚至是内置或shell函数,都运行在单独的进程中,即运行管道的shell的子进程中。子进程不能影响其父进程的环境。当read命令将变量设置为输入,该变量仅在子shell中设置,而不是在父shell中设置。当子shell退出时,变量的值将丢失。

许多以read variable可以转换为命令替换,这将捕获指定命令的输出。然后,可以将输出分配给一个变量:

grep ^gnu /usr/lib/news/active | wc -l | read ngroup

可以转换成

ngroup=$(grep ^gnu /usr/lib/news/active | wc -l)

不幸的是,这并不能将文本拆分到多个变量中,就像给出多个变量参数时的Read一样。如果需要这样做,可以使用上面的命令替换将输出读入变量并使用bash模式删除扩展操作符分割变量,或者使用以下方法的一些变体。

例如/usr/local/bin/ipaddr是以下shell脚本:

#! /bin/shhost `hostname` | awk '/address/ {print $NF}'

而不是使用

/usr/local/bin/ipaddr | read A B C D

若要将本地机器的IP地址分解为单独的八进制,请使用

OIFS="$IFS"IFS=.set -- $(/usr/local/bin/ipaddr)IFS="$OIFS"A="$1" B="$2" C="$3" D="$4"

但是,请注意,这将改变shell的位置参数。如果你需要它们,你应该在做这件事之前先保存它们。

这是一般的方法-在大多数情况下,您不需要将$IFS设置为不同的值。

其他一些用户提供的替代方案包括:

read A B C D << HERE
    $(IFS=.; echo $(/usr/local/bin/ipaddr))HERE

如果过程替换可用,

read A B C D < <(IFS=.; echo $(/usr/local/bin/ipaddr))


查看完整回答
反对 回复 2019-05-30
  • 3 回答
  • 0 关注
  • 1670 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信