bash shell 脚本和脚本中函数的变量范围

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21006674/
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-18 09:12:00  来源:igfitidea点击:

Variable scope for bash shell scripts and functions in the script

linuxbashshellunix

提问by Classified

I'm a little confused with my script regarding functions, variable scope, and possibly subshells. I saw in another postthat pipes spawn a subshell and the parent shell can't access variables from the subshell. Is this the same case with cmds run in backticks too?

我对我的脚本关于函数、变量范围和可能的子外壳有点困惑。我在另一篇文章中看到管道产生了一个子外壳,而父外壳不能从子外壳访问变量。这与 cmds 在反引号中运行的情况相同吗?

To not bore people, I've shortened my 100+ line script but I tried to remember to leave in the important elements (i.e. backticks, pipes etc). Hopefully I didn't leave anything out.

为了不让人厌烦,我缩短了 100 多行脚本,但我尽量记住保留重要元素(即反引号、竖线等)。希望我没有遗漏任何东西。

global1=0
global2=0
start_read=true

function testfunc {
   global1=9999
   global2=1111
   echo "in testfunc"
   echo $global1
   echo $global2
}

file1=whocares
file2=whocares2

for line in `cat $file1`
do
   for i in `grep -P "\w+ stream" $file2 | grep "$line"`   # possible but unlikely problem spot
   do
         end=$(echo $i | cut -d ' ' -f 1-4 | cut -d ',' -f 1)   # possible but unlikely spot
         duration=`testfunc $end`       # more likely problem spot
   done
done

echo "global1 = $global1"
echo "global2 = $global2"

So when I run my script, the last line says global1 = 0. However, in my function testfunc, global1 gets set to 9999 and the debug msgs print out that within the function at least, it is 9999.

所以当我运行我的脚本时,最后一行说 global1 = 0。但是,在我的函数 testfunc 中,global1 被设置为 9999 并且调试消息至少在函数内打印出来,它是 9999。

Two questions here:

这里有两个问题:

  1. Do the backticks spawn a subshell and thus making my script not work?
  2. How do I work around this issue?
  1. 反引号是否会产生一个子shell,从而使我的脚本不起作用?
  2. 我该如何解决这个问题?

Thanks in advance for your help.

在此先感谢您的帮助。

采纳答案by damienfrancois

You can try something like

你可以尝试类似的东西

global1=0
global2=0
start_read=true

function testfunc {
   global1=9999
   global2=1111
   echo "in testfunc"
   echo $global1
   echo $global2
   duration=something
}

file1=whocares
file2=whocares2

for line in `cat $file1`
do
   for i in `grep -P "\w+ stream" $file2 | grep "$line"`   # possible but unlikely problem spot
   do
         end=$(echo $i | cut -d ' ' -f 1-4 | cut -d ',' -f 1)   # possible but unlikely spot
         testfunc $end       # more likely problem spot
   done
done

echo "global1 = $global1"
echo "global2 = $global2"

回答by anubhava

Do the backticks spawn a subshell and thus making my script not work?:

Do the backticks spawn a subshell and thus making my script not work?

Yes they do and any changes made in variable in a subshell are not visible in parent shell.

是的,在子 shell 中对变量所做的任何更改在父 shell 中都不可见。

How do I work around this issue?

How do I work around this issue?

You can probably try this loop that avoid spawning a subshell:

你可以试试这个避免产生子shell的循环:

while read line
do
   while read i
   do
      end=$(echo $i | cut -d ' ' -f 1-4 | cut -d ',' -f 1)
      duration=$(testfunc "$end")
   done < <(grep -P "\w+ stream" "$file2" | grep "$line")
done < "$file1"

PS: But testfuncwill still be called in sub process.

PS:但testfunc仍会在子进程中调用。