bash 循环退出后的局部变量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2060082/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-17 21:32:43  来源:igfitidea点击:

Local variables after loop exit

bash

提问by Leo

I am having some issues with local variables after exiting a loop. The variable maxends up with the value 0, despite the code below:

退出循环后,我遇到了局部变量的一些问题。max尽管有下面的代码,但变量最终的值为 0:

max=0
cat tmp|while read line
do
temp=$(echo $line|tr -d "\n"|wc -c)
if [ $temp -gt $max ];then

max=$temp
echo $max
fi
done
echo -n tmp $max

cat tmp
12345
123456

And this is the output I receive:

这是我收到的输出:

5
6
 tmp 0

I don't understand why maxis 0 after exiting the loop, while inside the loop it finds the correct values.

我不明白为什么max退出循环后为 0,而在循环内它会找到正确的值。

回答by Ignacio Vazquez-Abrams

A pipe starts a new subshell, with its own environment and variable space. Use < tmpat the end of the loop instead.

管道启动了一个新的子shell,它有自己的环境和变量空间。< tmp改为在循环结束时使用。

回答by Paul Creasey

max=0
while read line
do
    temp=$(echo $line|tr -d "\n"|wc -c)
    if [ $temp -gt $max ]
    then 
        max=$temp
        echo $max
    fi
done <tmp
echo -n tmp $max

回答by lwho

According to the bash man page each command in a pipeline is executed in a subshell. That is, your while loop runs in a subshell and only the value of the variable max in that subshell is modified.

根据 bash 手册页,管道中的每个命令都在子外壳中执行。也就是说,您的while 循环在子shell 中运行,并且仅修改该子shell 中变量max 的值。

Variables of subshells are not propagated back to the calling shell, which is running the echo command and thus still sees the initial zero value.

子外壳的变量不会传播回调用外壳,后者正在运行 echo 命令,因此仍会看到初始零值。

If you run the echo in the same subshell (note the curly braces) it will work:

如果您在同一个子 shell 中运行 echo(注意花括号),它将起作用:

max=0
cat tmp|{
    while read line
    do
        temp=$(echo $line|tr -d "\n"|wc -c)
        if [ $temp -gt $max ];then
            max=$temp
        fi
    done
    echo -n tmp $max
}

If you need the value for further calculations in the outer shell, you would need to use command substitution like this:

如果您需要在外壳中进一步计算的值,则需要使用如下命令替换:

max=0
max=$(cat tmp|{
    while read line
    do
        temp=$(echo $line|tr -d "\n"|wc -c)
        if [ $temp -gt $max ];then
            max=$temp
        fi
    done
    echo -n $max
})
echo tmp $max

回答by dustmachine

The pipe before your while is putting everything inside the loop into a separate shell, and thus a separate identifier context (essentially a new environment).

while 之前的管道将循环内的所有内容放入一个单独的 shell 中,因此是一个单独的标识符上下文(本质上是一个新环境)。

Redirecting the tmpfile into the whileloop via <will keep your loop and variables all in the same execution context.

tmp文件重定向到while循环 via<将使您的循环和变量都保持在相同的执行上下文中。

while read line
do
    # your loop stuff 
done < tmp

回答by ghostdog74

Here's a one liner in awk.

这是 awk 中的一个单行。

$ awk 'length>t{t=length}END{print t}' file
6