我有一个包含grep要从另一个程序的输出中排除的字符串的数组。我需要-e在每个元素之前添加一个。例如:
exclude=("$0" /usr/sbin/crond)
needs-restarting | grep -Fwiv "${exclude[@]}"
Run Code Online (Sandbox Code Playgroud)
现在我知道在这种情况下我可以像这样在每个元素之前添加--regexp=(或只是-e):
exclude=( "${exclude[@]/#/--regexp=}" )
但在一般情况下,我将如何处理?我想出了这个,但也许有一个更简单的方法。
i=0
for elem in "${exclude[@]}"; do
exclude[i]='-e'
exclude[i+1]="$elem"
((i+=2))
done
declare -p exclude
Run Code Online (Sandbox Code Playgroud)
在bash4.4+ 中,您可以执行以下操作:
readarray -td '' array < <(
((${#array[@]})) && printf -- '-e\0%s\0' "${array[@]}"
)
Run Code Online (Sandbox Code Playgroud)
这里\0用作分隔符,因为 bash 变量无论如何都不能包含 NUL 字节。如果您知道数组不会为空,则可以跳过((${#array[@]})) &&.
例子:
bash-5.0$ array=($'a\nb' '' 'c d' e)
bash-5.0$ typeset -p array
declare -a array=([0]=$'a\nb' [1]="" [2]="c d" [3]="e")
Run Code Online (Sandbox Code Playgroud)
bash-5.0$ typeset -p array
declare -a array=([0]="-e" [1]=$'a\nb' [2]="-e" [3]="" [4]="-e" [5]="c d" [6]="-e" [7]="e")
Run Code Online (Sandbox Code Playgroud)
在 中zsh,您可以使用其数组压缩运算符:
opt=-e
(($#array == 0)) || array=("${(@)opt:^^array}")
Run Code Online (Sandbox Code Playgroud)
或者这个令人费解的:
set -o extendedglob # for (#m)
array=("${(Q@)"${(@z)array//(#m)*/-e ${(qq)MATCH}}"}")
Run Code Online (Sandbox Code Playgroud)
我们用-e <the-element-quoted>(with the qqflag)替换每个元素,然后使用z将引用解析回元素列表( where-e和<the-element-quoted>then 被分离出来),并Q删除引号(以及@用于保留空元素的引号内(如果有的话) )。