我有一个 bash 函数,其参数是文件。因此,以下打印语句给出
opts="$@"
echo "$fargs"
Result:
linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~
我有两个数组incl
,excl
用于存储要处理的文件类型。
Example: incl=( .rc )
我想要创建两个列表。一个列表包含与数组中的文件类型匹配的文件 incl
(例如,带有.rc
扩展名的文件)。另一个列表包含文件类型不匹配的文件名(例如,带有扩展名的文件.rc~
)。
从一个简单的循环开始
fargs="$@"
local f ty aggr=()
for f in $fargs; do
for ty in "${incl[@]}"; do
[[ "$f" =~ *${ty}$ ]] && aggr+=( "$f" )
done
done
echo "$fargs"
echo
echo "${incl[@]}"
echo
echo " aggr:"
echo " ${aggr[*]}"
但有些不对劲,因为我总是得到一个空aggr
数组。
dvorak linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~
.rc
aggr:
答案1
主要问题是您将正则表达式语法($
行锚点)与 glob 模式语法(前导*
通配符)混合在一起,您可以通过一个简单的测试来验证:
$ ty=.rc; [[ foo.rc =~ *${ty}$ ]] ; echo $?
2
(语法有效测试的退出状态应该是 0 或 1)。
您的测试可以是
[[ "$f" =~ ${ty}$ ]] # regex
或者
[[ "$f" = *${ty} ]] # glob pattern
同样,fargs="$@"
是标量赋值;for f in $fargs
然后,不带引号的变量会在空格处拆分 (string) 变量 - 如果任何文件名包含空格,则会中断。您应该使用fargs=("$@")
然后for f in "${fargs[@]}"
。或者,直接循环遍历位置参数,或者for f in "$@"
,POSIXLY,只需for f
:
#!/bin/bash
myfunc () {
local f ty aggr=()
for f do
for ty in "${incl[@]}"; do
[[ "$f" = *${ty} ]] && aggr+=( "$f" )
done
done
printf '%s\n' "${aggr[@]}"
}
incl=( .rc )
myfunc linge-cellar.rc linge-cellar.rc~ linge-checkn.rc linge-checkn.rc~ \
linge-comint.rc linge-comint.rc~ linge-comseq.rc linge-comseq.rc~ \
linge-console.rc linge-console.rc~ linge-curiplaya.rc linge-curiplaya.rc~ \
linge-dircolors.rc linge-dircolors.rc~ linge-firefly.rc linge-firefly.rc~ \
linge-mosaic.rc linge-mosaic.rc~ linge-profile.rc opcon-cellar.rc~
测试:
$ ./myscript
linge-cellar.rc
linge-checkn.rc
linge-comint.rc
linge-comseq.rc
linge-console.rc
linge-curiplaya.rc
linge-dircolors.rc
linge-firefly.rc
linge-mosaic.rc
linge-profile.rc
在 zsh 中,可以通过${name:#pattern}
对位置参数数组应用参数扩展来避免内部循环,并使用M
修饰符删除不匹配的元素(默认情况下,不带M
,会删除匹配的元素):
#!/bin/zsh
myfunc () {
local ty aggr=()
for ty in ${incl[@]}; do
aggr+=( ${(M)@:#*${ty}} )
done
print -rC1 ${aggr[@]}
}
参见此类似的 Unix 和 Linux 答案有没有一种简单的方法来获取所有不以连字符开头的参数的数组?