如何匹配bash正则表达式中的“什么都没有”?

时间:2012-05-14 03:57:05

标签: regex bash

我无法使用bash正则表达式捕获此格式(t|b|bug_|task_|)1234字符串中的数字。以下不起作用:

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]]

但是一旦我把它改成这样的东西:

[[ $current_branch =~ ^(t|b|bug_|task_)([0-9]+) ]]

它有效,但当然是错误的,因为它没有涵盖没有前缀的情况。我意识到在这种情况下我可以做到

[[ $current_branch =~ ^(t|b|bug_|task_)?([0-9]+) ]]

并获得相同的结果,但我想知道为什么第二个例子不起作用。例如,正则表达式似乎在Ruby中运行良好。

(这是GNU bash, version 3.2.48(1)-release (x86_64-apple-darwin11),OSX Lion)

2 个答案:

答案 0 :(得分:3)

我确信正则表达式的工作版本和非工作版本之间的区别在于阅读regex (7)的不同方式。我将引用整个相关部分,因为我认为这是你问题的核心所在:


  

POSIX.2中定义的正则表达式(“RE”)有两种形式:现代          RE(大致是egrep; POSIX.2称之为“扩展”RE)并且已过时          RE(大约是ed(1); POSIX.2“基本”RE的那些)。过时的RE主要存在          为了在一些旧程序中向后兼容;他们将在讨论          结束。 POSIX.2保留了RE语法和语义的某些方面; “(!)“ 分数          关于这些方面的决定可能无法完全移植到其他POSIX.2          的实施方式。

     

(现代)RE是一个(!)或更多非空(!)分支,用“|”分隔。它          匹配任何与其中一个分支匹配的东西。

     

分支是一个(!)或更多,连接在一起。它匹配的匹配          首先,然后匹配第二个,等等。

     

一个片段是 atom ,可能后跟一个(!)'*','+','?'或绑定。          后跟'*'的原子匹配原子的0或更多匹配的序列。          后跟'+'的原子匹配原子的1个或多个匹配的序列。          一个原子后跟'?'匹配原子的0或1个匹配的序列。

     

绑定是'{'后跟无符号十进制整数,可能后跟          ','可能后跟另一个无符号十进制整数,后跟始终          '}'。整数必须介于0和RE_DUP_MAX(255(!))之间,并且          如果有两个,第一个可能不会超过第二个。一个原子          后跟一个包含一个整数i的边界,并且没有逗号匹配一个序列          正好与原子的匹配。一个原子后跟一个含有一个的边界          整数i和逗号匹配原子的一个或多个匹配的序列。一个          原子后跟一个包含两个整数的边界i和j匹配一个序列          我通过原子的j(包括)匹配。

     

原子是用“()”括起来的正则表达式(匹配的匹配)          正则表达式),一组空的“()”(匹配空字符串)(!),a          括号表达式(见下文),'。' (匹配任何单个字符),'^'          (匹配行开头的空字符串),'$'(匹配null          字符串在一行的末尾),一个'\'后跟一个字符          “^。[$()| * +?{\”(将该字符作为普通字符匹配),'\'          后跟任何其他字符(!)(匹配该字符作为          普通字符,好像'\'不存在(!)),或单个字符          没有其他意义的字符(匹配该字符)。一个 '{'          其次是数字以外的字符是普通字符,而不是          一个边界(!)的开头。使用'\'结束RE是违法的。


好的,这里有很多东西需要打开包装。首先,请注意“(!)”符号表示存在开放或不可移植的问题。

基本问题在下一段:

  

(现代)RE是一个(!)或更多非空(!)分支,用'|'分隔。

你的情况是你有一个空分支。正如您从“(!)”中看到的那样,空分支是一个开放或不可移植的问题。我认为这就是为什么它适用于某些系统但不适用于其他系统。 (我在Cygwin 4.1.10(4)上测试了它 - 发布它并没有用,然后在Linux 3.2.25(1)上发布 - 它发生了。这两个系统有相同但不完全相同的手册页 regex7 。)

假设分支必须是非空的,分支可以是一个分支,可以是一个原子。

原子可以是“空集”()“(匹配空字符串)(!)”。 <sarcasm>嗯,这真的很有帮助。</sarcasm>所以,POSIX指定空字符串的正则表达式,即(),但也附加一个“(!)”,表示这是一个公开的问题,或者不是便携式的。

由于您要查找的是与空字符串匹配的分支,请尝试

[[ $current_branch =~ ^(t|b|bug_|task_|())([0-9]+) ]]

使用()正则表达式匹配空字符串。 (这在我的Cygwin 4.1.10(4) - 释放shell中对我有用,你的原始正则表达式没有。)

然而,虽然(希望)此建议在您当前的设置中对您有用,但无法保证它是可移植的。抱歉让人失望。

答案 1 :(得分:0)

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]]在bash 4.1.2中适用于我,但在bash 3.2.48中失败。它可能只是两个版本之间修复的错误。