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开始和结束的位置。