Bash 双括号全局匹配的替代方案

Bash 双括号全局匹配的替代方案

鉴于

hasArgs=a:b:c:
x=b
if [[ ${hasArgs} = *$x:* ]] ; then …

我希望我可以用一个不太特定于 Bash 的替代方案来替换上面的双括号测试(意味着没有子 shell/命令等)

参数扩展没有帮助,因为它不消耗变量。

if [ "${hasArgs}" != "${hasArgs#$x:}" ] ; then …

是否有适合此用例的简单(一行)解决方案?

答案1

它不是一行代码,但它具有很强的可读性,并且可以扩展以检查任意数量的参数:

hasArgs="a:b:c"
x=b
case "$hasArgs" in
    *$x*)
        echo "$x is present"
        ;;
esac

答案2

以下内容将在 sh 中运行:

if echo "$hasArgs" | grep -q "$x"; then

答案3

实际上,您可以在这里使用标准参数扩展(您只是缺少通配符):

$ args=a:b:c:
$ x=b
$ echo "${args%$x:*}"
a:
$ if [ "$args" != "${args#*$x:}" ]; then echo 'b: is present'; fi
b: is present

(或同等"${args%$x:*}"

缺点是你需要在 后面加上冒号b,所以a:b或者普通的b不会匹配,但它也会匹配a:bb:c。 ([[ $var = *$x:* ]]以及明显的模式匹配也case有同样的缺点。)

匹配所有b, b:c, a:b, a:b:c, 而不匹配a:bb:c会有点棘手。我能想到的就是这样的:

args=a:b:c
x=b
IFS=:                   # affects globally
set -f                  # affects globally...
for x in $args; do
    if [ "$x" = "b" ]; then
        echo "b is present"
    fi
done

除非你想把所有的情况都写出来:

args=a:b:c
x=b
found=0
case "$args" in
    $x)     found=1;;
    $x:*)   found=1;;
    *:$x)   found=1;;
    *:$x:*) found=1;;
esac
if [ "$found" = 1 ]; then ...; fi

使用正则表达式(在 Bash 中)更容易:

args=b:c
x=b
if [[ $args =~ (^|:)$x(:|$) ]]; then
    echo "b found"
fi

相关内容