【问题标题】:Variable scope for bash shell scripts and functions in the script脚本中 bash shell 脚本和函数的变量范围
【发布时间】:2014-01-08 21:15:13
【问题描述】:

关于函数、变量范围和可能的子shell,我对我的脚本有点困惑。 我在另一个post 中看到管道生成一个子shell,而父shell 无法从子shell 访问变量。在反引号中运行的 cmd 是否也是这种情况?

为了不让人感到厌烦,我缩短了 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"

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

这里有两个问题:

  1. 反引号是否生成子shell,从而使我的脚本不 工作?
  2. 如何解决此问题?

【问题讨论】:

  • 1.是的,他们这样做 2. 快速修复:删除反引号并在函数定义中移动分配。或者写 global1= `testfunc $end `
  • 顺便说一句,那些嵌套的for 循环看起来非常扭曲且效率低下。我猜你想说grep -P "\w+ stream" "$file2" | grep -f "$file1" | while read i; do...
  • @damienfrancois,谢谢您的回复。 testfunc 修改了几个全局变量。我想这是我忘记包括在内的一件事。
  • 好的,那么您可以尝试用简单的testfunc $end 替换duration= ` testfunc $end ` 并在函数体中添加duration=...。您真的可以将 bash 函数视为简单地内联扩展的宏。

标签: linux bash shell unix


【解决方案1】:

你可以试试

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"

【讨论】:

  • 与OP脚本的区别:(1) 函数体中增加了duration=something(2) 循环中的duration=`testfunc $end` 已更改为testfunc $end
【解决方案2】:

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

是的,它们确实如此,并且在子 shell 中对变量所做的任何更改在父 shell 中都不可见。

How do I work around this issue?

你可以试试这个避免产生子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: 但testfunc 仍会在子进程中调用。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-22
    相关资源
    最近更新 更多