grep
我有一个包含要从另一个程序的输出中排除的字符串的数组。我需要-e
在每个元素之前添加一个。例如:
exclude=("$0" /usr/sbin/crond)
needs-restarting | grep -Fwiv "${exclude[@]}"
现在我知道在这种情况下我可以在每个元素前面添加--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
答案1
在bash
4.4+ 中,你可以这样做:
readarray -td '' array < <(
((${#array[@]})) && printf -- '-e\0%s\0' "${array[@]}"
)
这里用作\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")
- 后:
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")
在 中zsh
,您可以使用其数组压缩运算符:
opt=-e
(($#array == 0)) || array=("${(@)opt:^^array}")
或者这个复杂的:
set -o extendedglob # for (#m)
array=("${(Q@)"${(@z)array//(#m)*/-e ${(qq)MATCH}}"}")
-e <the-element-quoted>
我们用(with the flag)替换每个元素qq
,然后使用z
将引用解析回元素列表(其中-e
和<the-element-quoted>
然后被分隔出来),并Q
删除引号(以及@
用于保留空元素(如果有)的引号内) )。
答案2
您可以稍微简化您建议的循环:
exclude_args=()
for elem in "${exclude[@]}"; do
exclude_args+=('-e' "$elem")
done
exclude=("${exclude_args[@]}") # Optional, if you want to replace the original array's contents