【问题标题】:How can I match spaces with a regexp in Bash?如何在 Bash 中将空格与正则表达式匹配?
【发布时间】:2017-08-02 14:09:54
【问题描述】:

我希望下面的代码回显“是”,但事实并非如此。由于某种原因,它与单引号不匹配。为什么?

str="{templateUrl: '}"
regexp="templateUrl:[\s]*'"

if [[ $str =~ $regexp ]]; then
  echo "yes"
else
  echo "no"
fi

【问题讨论】:

    标签: regex bash


    【解决方案1】:

    替换:

    regexp="templateUrl:[\s]*'"
    

    与:

    regexp="templateUrl:[[:space:]]*'"
    

    根据man bash=~ 运算符支持man 3 regex 中定义的“扩展正则表达式”。 man 3 regex 表示它支持 POSIX 标准并将读者推荐给 man 7 regex。 POSIX 标准支持[:space:] 作为空格的字符类。

    GNU bash manual 记录了支持的字符类,如下所示:

    在‘[’和‘]’中,可以使用 语法 [:class:],其中 class 是定义的以下类之一 在 POSIX 标准中:

    alnum alpha ascii 空白 cntrl 数字图下方打印
    punct 空格高位字xdigit

    我在 GNU bash 文档中发现 \s 的唯一提及是在提示符中的不相关使用,例如 PS1,而不是在正则表达式中。

    *的含义

    [[:space:]] 将匹配一个空白字符。 [[:space:]]* 将匹配 零个或多个 个空格字符。

    spaceblank的区别

    POSIX regular expressions 提供两类空白:[[:space:]][[:blank:]]

    • [[:blank:]] 表示空格和制表符。这使它类似于:[ \t]

    • [[:space:]] 除了空格和制表符之外,还包括换行符、换行符、换页符和垂直制表符。这使它类似于:[ \t\n\r\f\v]

    使用字符类的一个关键优势是它们对于 unicode 字体是安全的。

    【讨论】:

    • 注意[:space:]表示所有空格,包括回车和换行;而[:blank:] 表示“水平”空白(空格和制表符) -- regular-expressions.info/posixbrackets.html
    • 为了匹配一个文字空间,你也可以用反斜杠转义它,即:regexp="templateUrl:\ *'"
    • @ChristophThiede 是的,这是真的。但实际上,您不需要反斜杠。 regexp="templateUrl: *'" 也可以。当然,无论哪种情况,这都会将正则表达式限制为匹配实际的 ASCII 空白。 [[:blank:]][[:space:]] 可能识别的其他空白字符不匹配。
    【解决方案2】:

    去掉正则表达式中的方括号:

    regexp="templateUrl:\s*'"
    

    存在方括号时,内部的\s 被逐字解释为匹配\s 字符,但您的意图显然是匹配\s 是简写的空白字符类(因此不需要方括号)。

    $ uname -a
    Linux noname 3.13.0-24-generic #47-Ubuntu SMP Fri May 2 23:30:00 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
    $ bash --version
    GNU bash, version 4.3.11(1)-release (x86_64-pc-linux-gnu)
    Copyright (C) 2013 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    
    This is free software; you are free to change and redistribute it. 
    There is NO WARRANTY, to the extent permitted by law.
    $ cat test.sh
    str="{templateUrl: '}" 
    regexp="templateUrl:\s*'"
    
    if [[ $str =~ $regexp ]]; then
      echo "yes"
    else
      echo "no"
    $ bash test.sh
    yes 
    

    【讨论】:

    • 你测试了吗?对我来说,使用 regexp="templateUrl:\s*'" 仍然会回显“不”。
    • 我逐字运行了您的脚本 - 它为我回显了 yes。我在 Linux Mint 17 机器上运行。我会更新答案以反映这一点。
    • 你说得对,我切换到 Mac 并从我的 Linux 机器上得到了不同的结果。似乎 OS X 上的 bash(至少是你和我所拥有的风格)默认为严格的 POSIX 表示法 - 你应该使用@John1024 或 heemayl 的答案
    【解决方案3】:

    这应该可行:

    #!/bin/bash
    str="{templateUrl: '}"
    regexp="templateUrl:[[:space:]]*'"
    
    if [[ $str =~ $regexp ]]; then
      echo "yes"
    else
      echo "no"
    fi
    

    如果要匹配零个或多个空格,则需要在 [[:space:]] 之后添加 *

    【讨论】:

    • * 似乎是需要的。
    • 在我的GNU bash, version 4.2.25 中不需要它。
    • 我明白了。呃,这太烦人了。
    • @crzrcn 如果要匹配零个或多个空格,则需要*。如果您想完全匹配一个空格,则不需要。
    • 是的,这就是为什么我说它似乎是必要的。我想匹配零个或多个空格。
    猜你喜欢
    • 2023-03-14
    • 2013-06-29
    • 1970-01-01
    • 1970-01-01
    • 2014-03-25
    • 1970-01-01
    • 2013-02-26
    • 2010-10-08
    相关资源
    最近更新 更多