如何在Bash中使用正则表达式匹配空格?

57

我期望以下代码输出"yes",但它没有。由于某些原因它无法匹配单引号。为什么呢?

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

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

108

替换:

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

使用:

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

根据 man bash=~ 运算符支持 "extended regular expressions",并在 man 3 regex 中定义。 man 3 regex 表示它支持 POSIX 标准,并引用读者到 man 7 regex。POSIX 标准支持使用 [:space:] 作为空格的字符类。 GNU bash 手册 记录了支持的字符类如下:

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

alnum alpha ascii blank cntrl digit graph lower print
punct space upper word xdigit

我在 GNU bash 文档中找到的唯一提到 \s 的地方是与提示符(例如 PS1)中的无关用途,而不是正则表达式中。

* 的含义

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

spaceblank 的区别

POSIX 正则表达式 提供了两个空格类: [[:space:]][[:blank:]]
  • [[:blank:]] 表示空格和制表符。 这使它类似于: [ \t]

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

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

4
请注意,[:space:] 意味着所有空格,包括回车和换行;而 [:blank:] 意味着“水平”的空格(空格和制表符)-- http://www.regular-expressions.info/posixbrackets.html - glenn jackman
1
仅匹配字面空格,您也可以使用反斜杠进行转义,即:regexp="templateUrl:\ *'" - Christoph Thiede
1
@ChristophThiede 是的,没错。实际上,你不需要反斜杠。regexp="templateUrl: *'"也可以工作。当然,在任何情况下,这都限制了正则表达式匹配实际的ASCII空格。其他可能被[[:blank:]][[:space:]]识别的空白字符不会被匹配。 - John1024

4

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

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*'" 对我仍然输出 "no" 。 - user810606
我按照你的脚本原样运行了一遍,并且它对我回显了“yes”。我正在运行Linux Mint 17系统。我会更新答案以反映这一点。 - rchang
2
你说得对,我换成了 Mac 电脑后,与我的 Linux 系统得到了不同的结果。看起来,在 OS X 上的 bash(至少是你和我使用的版本)默认采用严格的 POSIX 符号 - 你应该采用 @John1024 或 heemayl 的答案。 - rchang

3
这应该有效:

#!/bin/bash
str="{templateUrl: '}"
regexp="templateUrl:[[:space:]]*'"

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

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

似乎需要使用 * - user810606
在我的 GNU bash,版本4.2.25 中不需要它。 - heemayl
1
我明白了。唉,这真的很烦人。 - user810606
@crzrcn 如果您想匹配零个或多个空格,则需要使用 *。如果您想匹配 恰好 一个空格,则不需要使用它。 - John1024
是的,这就是为什么我说似乎需要它。我想匹配零个或多个空格。 - user810606

0
这是另一种可行的方法,如果您只想从空格字符类中获取空格。
#!/bin/bash
str="{templateUrl: '}"
if [[ $str =~ templateUrl:" "*"'" ]]; then
  echo "yes"
else
 echo "no"
fi

感谢 Malak Younes。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接