从管道命令附加到数组变量 [英] Append to an array variable from a pipeline command
问题描述
我正在编写一个bash函数来获取所有git存储库,但是当我要将所有git存储库路径名存储到数组patharray
时遇到了一个问题.这是代码:
I am writing a bash function to get all git repositories, but I have met a problem when I want to store all the git repository pathnames to the array patharray
. Here is the code:
gitrepo() {
local opt
declare -a patharray
locate -b '\.git' | \
while read pathname
do
pathname="$(dirname ${pathname})"
if [[ "${pathname}" != *.* ]]; then
# Note: how to add an element to an existing Bash Array
patharray=("${patharray[@]}" '\n' "${pathname}")
# echo -e ${patharray[@]}
fi
done
echo -e ${patharray[@]}
}
我想将所有存储库路径保存到patharray
数组,但是我无法在由locate
和while
命令组成的pipeline
之外获取它.
但是我可以在pipeline
命令中获取数组,如果没有注释,带注释的命令# echo -e ${patharray[@]}
效果很好,那么我该如何解决该问题?
I want to save all the repository paths to the patharray
array, but I can't get it outside the pipeline
which is comprised of locate
and while
command.
But I can get the array in the pipeline
command, the commented command # echo -e ${patharray[@]}
works well if uncommented, so how can I solve the problem?
我已经尝试过export
命令,但是似乎无法将patharray
传递给管道.
And I have tried the export
command, however it seems that it can't pass the patharray
to the pipeline.
推荐答案
首先,最好使用array[${#array[*]}]="value"
或array+=("value1" "value2" "etc")
附加到数组变量上,除非您希望变换整个数组(您不希望这样做). t).
First of all, appending to an array variable is better done with array[${#array[*]}]="value"
or array+=("value1" "value2" "etc")
unless you wish to transform the entire array (which you don't).
现在,因为运行了流水线命令在子流程中,在管道命令内部对变量所做的更改不会传播到外部.有几种解决方法(大多数列出在 Greg的BashFAQ/024 中):
Now, since pipeline commands are run in subprocesses, changes made to a variable inside a pipeline command will not propagate to outside it. There are a few options to get around this (most are listed in Greg's BashFAQ/024):
-
改为通过stdout传递结果
- 最简单的;您仍然需要这样做以从函数中获取值(尽管那里是返回适当变量的方法)
- the simplest; you'll need to do that anyway to get the value from the function (although there are ways to return a proper variable)
any special characters in paths can be handled reliably by using
\0
as a separator (see Capturing output of find . -print0 into a bash array for reading\0
-separated lists)
locate -b0 '\.git' | while read -r -d '' pathname; do dirname -z "$pathname"; done
或者简单地
locate -b0 '\.git' | xargs -0 dirname -z
避免在子进程中运行循环
-
完全避免使用管道
avoid pipeline at all
- 临时文件/FIFO(不好:需要手动清理,其他人可以访问)
- 临时变量(中等:不必要的内存开销)
-
进程替换(特殊的,语法支持的FIFO情况,不需要手动清理;代码改编自格雷格的BashFAQ/020 ):
i=0 #`unset i` will error on `i' usage if the `nounset` option is set
while IFS= read -r -d $'\0' file; do
patharray[i++]="$(dirname "$file")" # or however you want to process each file
done < <(locate -b0 '\.git')
使用lastpipe
选项(Bash 4.2中的新增功能)-不在子进程中运行管道的 last 命令(中等:具有全局效果)
use the lastpipe
option (new in Bash 4.2) - doesn't run the last command of a pipeline in a subprocess (mediocre: has global effect)
这篇关于从管道命令附加到数组变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!