如何在案例陈述中使用模式?

发布于 2024-10-10 01:36:52 字数 370 浏览 3 评论 0 原文

man 页面显示 case 语句使用“文件名扩展模式匹配”。
我通常希望某些参数有简短的名称,所以我尝试:

case $1 in
    req|reqs|requirements) TASK="Functional Requirements";;
    met|meet|meetings) TASK="Meetings with the client";;
esac

logTimeSpentIn "$TASK"

我尝试了像 req*me{e,}t 这样的模式,我知道它们会正确扩展以匹配这些值在文件名扩展的上下文中,但它不起作用。

The man page says that case statements use "filename expansion pattern matching".
I usually want to have short names for some parameters, so I go:

case $1 in
    req|reqs|requirements) TASK="Functional Requirements";;
    met|meet|meetings) TASK="Meetings with the client";;
esac

logTimeSpentIn "$TASK"

I tried patterns like req* or me{e,}t which I understand would expand correctly to match those values in the context of filename expansion, but it doesn't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

兰花执着 2024-10-17 01:36:52

大括号扩展不起作用,但 *?[] 起作用。如果您设置了shopt -s extglob,那么您还可以使用扩展模式匹配

  • ?() - 模式出现零次或一次
  • *() - 模式出现零次或多次
  • +() - 出现一次或多次模式
  • @() - 出现一次模式
  • !() - 除模式之外的任何内容

这是一个示例:

shopt -s extglob
for arg in apple be cd meet o mississippi
do
    # call functions based on arguments
    case "$arg" in
        a*             ) foo;;    # matches anything starting with "a"
        b?             ) bar;;    # matches any two-character string starting with "b"
        c[de]          ) baz;;    # matches "cd" or "ce"
        me?(e)t        ) qux;;    # matches "met" or "meet"
        @(a|e|i|o|u)   ) fuzz;;   # matches one vowel
        m+(iss)?(ippi) ) fizz;;   # matches "miss" or "mississippi" or others
        *              ) bazinga;; # catchall, matches anything not matched above
    esac
done

Brace expansion doesn't work, but *, ? and [] do. If you set shopt -s extglob then you can also use extended pattern matching:

  • ?() - zero or one occurrences of pattern
  • *() - zero or more occurrences of pattern
  • +() - one or more occurrences of pattern
  • @() - one occurrence of pattern
  • !() - anything except the pattern

Here's an example:

shopt -s extglob
for arg in apple be cd meet o mississippi
do
    # call functions based on arguments
    case "$arg" in
        a*             ) foo;;    # matches anything starting with "a"
        b?             ) bar;;    # matches any two-character string starting with "b"
        c[de]          ) baz;;    # matches "cd" or "ce"
        me?(e)t        ) qux;;    # matches "met" or "meet"
        @(a|e|i|o|u)   ) fuzz;;   # matches one vowel
        m+(iss)?(ippi) ) fizz;;   # matches "miss" or "mississippi" or others
        *              ) bazinga;; # catchall, matches anything not matched above
    esac
done
左秋 2024-10-17 01:36:52

我认为你不能使用大括号。

根据 Bash 手册中关于 条件构造 中的情况。

每个模式都有波形符
扩展、参数扩展、
命令替换和算术
扩展。

不幸的是,没有关于大括号扩展的信息。

所以你必须做这样的事情:

case $1 in
    req*)
        ...
        ;;
    met*|meet*)
        ...
        ;;
    *)
        # You should have a default one too.
esac

I don't think you can use braces.

According to the Bash manual about case in Conditional Constructs.

Each pattern undergoes tilde
expansion, parameter expansion,
command substitution, and arithmetic
expansion.

Nothing about Brace Expansion unfortunately.

So you'd have to do something like this:

case $1 in
    req*)
        ...
        ;;
    met*|meet*)
        ...
        ;;
    *)
        # You should have a default one too.
esac
流星番茄 2024-10-17 01:36:52

ifgrep -Eq

arg='abc'
if printf '%s' "$arg" | grep -Eq 'a.c|d.*'; then
  echo 'first'
elif printf '%s' "$arg" | grep -Eq 'a{2,3}'; then
  echo 'second'
fi

其中:

  • -q 阻止 grep 生成输出,它只是产生退出状态
  • -E 启用扩展正则表达式

我喜欢这个,因为:

一个缺点是可能比 case 慢,因为它调用外部 grep 程序,但在使用 Bash 时我倾向于最后考虑性能。

case 是 POSIX 7

Bash 似乎默认遵循 POSIX,没有 https://stackoverflow.com/a/4555979/895245

这是引用:http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01 部分“案例条件构造”:

条件构造案例应执行与多个模式中的第一个相对应的复合列表(请参阅模式匹配符号)[...]具有相同复合列表的多个模式应由“|”分隔象征。 [...]

案例构造的格式如下:

大小写单词
   [(] 模式 1 ) 复合列表 ;;
   [[(] 模式[ | 模式] ... ) 复合列表 ;;] ...
   [[(] 模式[ | 模式] ... ) 复合列表]
埃萨克

然后 http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13部分“2.13.模式匹配表示法”仅提到*< /code> 和 []

if and grep -Eq

arg='abc'
if printf '%s' "$arg" | grep -Eq 'a.c|d.*'; then
  echo 'first'
elif printf '%s' "$arg" | grep -Eq 'a{2,3}'; then
  echo 'second'
fi

where:

  • -q prevents grep from producing output, it just produces the exit status
  • -E enables extended regular expressions

I like this because:

One downside is that this is likely slower than case since it calls an external grep program, but I tend to consider performance last when using Bash.

case is POSIX 7

Bash appears to follow POSIX by default without shopt as mentioned by https://stackoverflow.com/a/4555979/895245

Here is the quote: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_01 section "Case Conditional Construct":

The conditional construct case shall execute the compound-list corresponding to the first one of several patterns (see Pattern Matching Notation) [...] Multiple patterns with the same compound-list shall be delimited by the '|' symbol. [...]

The format for the case construct is as follows:

case word in
   [(] pattern1 ) compound-list ;;
   [[(] pattern[ | pattern] ... ) compound-list ;;] ...
   [[(] pattern[ | pattern] ... ) compound-list]
esac

and then http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_13 section "2.13. Pattern Matching Notation" only mentions ?, * and [].

南巷近海 2024-10-17 01:36:52

我已经多次遇到这个问答了,现在这是我的略有不同的观点。

我通常想要一些参数的简称

当然我也更喜欢较短的代码。然而......

case $1 in
    "req"|"reqs"|"requirements"|"many more"|"strings"| \
    "and"|"patterns"|"here")
        TASK="Functional Requirements";;
    "met"|"meet"|"meetings")
        TASK="Meetings with the client";;
esac

有效,并且我没有收到 shellcheck 的任何投诉。如果您愿意,您甚至可以将每个模式放在单独的行中,并按字母顺序对它们进行排序。

I came across this Q&A a few times now, here is my slightly different point of view now.

I usually want to have short names for some parameters

Of course I prefer shorter code too. However...

case $1 in
    "req"|"reqs"|"requirements"|"many more"|"strings"| \
    "and"|"patterns"|"here")
        TASK="Functional Requirements";;
    "met"|"meet"|"meetings")
        TASK="Meetings with the client";;
esac

... works, and I don't get any complaints from shellcheck. You could even put every pattern on a separate line and sort them alphabetically if that pleases you.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文