shell使用case语句匹配模式,case语句存储在变量中

8 shell posix sh

我试图将模式与case语句匹配,其中模式存储在变量中.这是一个最小的例子:

PATTERN="foo|bar|baz|bla"

case "foo" in
    ${PATTERN})
        printf "matched\n"
        ;;
    *)
        printf "no match\n"
        ;;
esac
Run Code Online (Sandbox Code Playgroud)

不幸的是"|" 似乎是逃脱了(有趣的是"*"或"?"不是).我如何让它工作,即匹配"foo"?我需要将模式存储在变量中,因为它是动态构造的.这需要在兼容POSIX的shell上运行.

buf*_*ufh 6

可以grep使用 的唯一符合 POSIX 标准的方法来匹配字符串中的子字符串sh(1p),而无需生成子进程(例如 ),如第 2.6.2 节“参数扩展”中所定义。

这是一个便利函数:

# Note:
# Unlike a regular expression, the separator *must* enclose the pattern;
# and it could be a multi chars.

isin() {
    PATTERN=${2:?a pattern is required}
    SEP=${3:-|}
    [ -z "${PATTERN##*${SEP}${1}${SEP}*}" ]
}
Run Code Online (Sandbox Code Playgroud)

例子:

for needle in foo bar; do
    isin "$needle" "|hello|world|foo|" && echo "found: $needle"
done

# using ";" as separator
for needle in foo bar; do
    isin "$needle" ";hello;world;foo;" \; && echo "found: $needle"
done

# using the string "RS" as separator
for needle in foo bar; do
    isin "$needle" "RShelloRSworldRSfooRS" RS && echo "found: $needle"
done
Run Code Online (Sandbox Code Playgroud)

case如果您想要两个世界,您可以将此解决方案与语句混合使用:

PATTERN="|foo bar|baz|bla|"

case "$needle" in
    xyz) echo "matched in a static part" ;;
    *)
        if [ -z "${PATTERN##*|${needle}|*}" ]; then
            echo "$needle matched $PATTERN"
        else
            echo "not found"
        fi
esac
Run Code Online (Sandbox Code Playgroud)

笔记

有时最好记住您可以在 中完成整个脚本awk(1p),这也是 POSIX,但我相信这是另一个答案。


Phi*_*ipp 1

您的模式实际上是模式列表,并且分隔符|必须按字面意思给出。你唯一的选择似乎是eval。但是,如果可以的话,请尽量避免这种情况。