Bash - 将变量的值传播到循环外部

时间:2022-03-08 00:23:41
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}

The echo statements outside of the loop do not display the expected variables. How should I make the contents of the variable propagate outside the loop?

循环外部的echo语句不显示预期变量。我应该如何使变量的内容在循环外传播?

3 个解决方案

#1


19  

The problem is the pipe, not the loop. Try it this way

问题是管道,而不是循环。试试这种方式吧

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}

You should also pre-declare globals for clarity, as shown above.

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

Pipes are executed in a subshell, as noted by Blagovest in his comment. Using process substitution instead (this is the < <(commands) syntax) keeps everything in the same process, so changes to global variables are possible.

正如布拉戈维斯特在评论中指出的那样,管道在子壳中执行。使用进程替换(这是<<(命令)语法)将所有内容保存在同一进程中,因此可以更改全局变量。

Incidentally, your pipeline could be improved as well

顺便提一下,您的管道也可以改进

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

One less invocation of grep to worry about.

少担心grep的一次调用。

#2


3  

This somewhat by-passes your question (and it's a good question), but you can achieve the same results using simply:

这有点绕过你的问题(这是一个很好的问题),但你可以使用简单的方法获得相同的结果:

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

The ($(cmd)) construct initialises a bash array using the output of the command within.

($(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

and you can get the number of elements using ${#_constr[*]}.

并且您可以使用$ {#_ constr [*]}获取元素数量。

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

#3


0  

Alternatively, you can move the echo statements inside the subshell:

或者,您可以在子shell中移动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}
)

Note the insertion of the parenthesis to explicitly define where the subshell begins and ends.

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

#1


19  

The problem is the pipe, not the loop. Try it this way

问题是管道,而不是循环。试试这种方式吧

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}

You should also pre-declare globals for clarity, as shown above.

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

Pipes are executed in a subshell, as noted by Blagovest in his comment. Using process substitution instead (this is the < <(commands) syntax) keeps everything in the same process, so changes to global variables are possible.

正如布拉戈维斯特在评论中指出的那样,管道在子壳中执行。使用进程替换(这是<<(命令)语法)将所有内容保存在同一进程中,因此可以更改全局变量。

Incidentally, your pipeline could be improved as well

顺便提一下,您的管道也可以改进

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

One less invocation of grep to worry about.

少担心grep的一次调用。

#2


3  

This somewhat by-passes your question (and it's a good question), but you can achieve the same results using simply:

这有点绕过你的问题(这是一个很好的问题),但你可以使用简单的方法获得相同的结果:

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

The ($(cmd)) construct initialises a bash array using the output of the command within.

($(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

and you can get the number of elements using ${#_constr[*]}.

并且您可以使用$ {#_ constr [*]}获取元素数量。

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

#3


0  

Alternatively, you can move the echo statements inside the subshell:

或者,您可以在子shell中移动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}
)

Note the insertion of the parenthesis to explicitly define where the subshell begins and ends.

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