将变量的值传播到循环外[重复]

Posted

技术标签:

【中文标题】将变量的值传播到循环外[重复]【英文标题】:Propagate value of variable to outside of the loop [duplicate] 【发布时间】:2011-11-15 11:19:03 【问题描述】:
dpkg --list |grep linux-image |grep "ii  " | while read line
do
  arr=($line)
  let i=i+1
  _constr+="$arr[2] "
done
echo $i
echo $_constr

循环外的 echo 语句不显示预期的变量。

我应该如何让变量的内容在循环外传播?

【问题讨论】:

请记住,while 循环在单独的进程中运行,这就是您看不到更改的变量的原因。 【参考方案1】:

问题是管道,而不是循环。试试这个方法

let i=0
declare -a arr

while read -r line ; do
    arr=($line)
    let i=i+1
    _constr+="$arr[2] "
done < <(dpkg --list |grep linux-image |grep "ii  ")

echo $i
echo $_constr

为了清楚起见,您还应该预先声明全局变量,如上所示。

正如 Blagovest 在他的评论中指出的那样,管道在子外壳中执行。使用process substitution instead(这是&lt; &lt;(commands) 语法)将所有内容保持在同一进程中,因此可以更改全局变量。

顺便说一句,您的管道也可以改进

dpkg --list |grep '^ii.*linux-image'

不用担心调用grep

【讨论】:

在 bash 3.x 中,循环的最后一行应该是 done &lt;&lt;&lt;`commands` @Ida:这样做有什么好处?这样做会失败:子shell将执行并在自己的行上返回每个结果,然后将其分解为单个字符串并立即馈送到read,它将读取直到第一个嵌入的换行符,循环一次然后@ 987654328@,没有更多的输入来处理,将终止。这不是你想要的。之后只有来自查询的第一个包版本会在 _constr 中。 bash 3.x 可以理解 &lt;() 构造。 +1 + done[space] 【参考方案2】:

这在某种程度上绕过了您的问题(这是一个很好的问题),但是您可以简单地使用以下方法获得相同的结果:

 _constr=($(dpkg --list | awk '/^ii.*linux-image/print $2'))

($(cmd)) 构造使用其中的命令输出初始化 bash 数组。

[me@home]$ echo $_constr[*]
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic
[me@home]$ echo $_constr[2]
linux-image-generic

你可以使用$#_constr[*]获取元素的数量。

[me@home]$ echo $#_constr[*]
3

【讨论】:

这确实是正确的做法。我没有要测试的 Debian 盒子,否则我会提出同样的建议。【参考方案3】:

或者,您可以将 echo 语句移动到子外壳中:

dpkg --list |grep linux-image |grep "ii  " | (
  let i=0
  declare -a arr

  while read line
  do
    arr=($line)
    let i=i+1
    _constr+="$arr[2] "
  done
  echo $i
  echo $_constr
)

注意插入括号以明确定义子shell的开始和结束位置。

【讨论】:

以上是关于将变量的值传播到循环外[重复]的主要内容,如果未能解决你的问题,请参考以下文章

在PHP中传播变量

如何将动作从 SKScene 组件传播到 UIViewController

传播解构以避免重复

同时不改变循环外变量的值。我需要制作一种以随机方式对数组进行洗牌的方法。 (C#请)[重复]

传播运算符在 console.log 中工作,但在尝试返回或设置变量时不起作用 [重复]

循环外未定义的变量[重复]