9

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

[[ $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)

4

2 回答 2

4

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


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

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

一个分支是一个(!)或多个片段,连接在一起。它匹配第一个匹配,然后匹配第二个匹配,依此类推。

一块是一个原子,可能后跟一个(!)'*'、'+'、'?'或bound。后跟“*”的原子匹配该原子的 0 个或多个匹配序列。后跟“+”的原子匹配该原子的 1 个或多个匹配的序列。一个原子后跟“?” 匹配原子的 0 或 1 个匹配序列。

边界是“{”后跟一个无符号十进制整数,可能后跟“,”,可能后跟另一个无符号十进制整数,总是后跟“}”。整数必须介于 0 和 RE_DUP_MAX (255(!)) 之间,如果有两个整数,则第一个不得超过第二个。一个原子后跟一个包含一个整数 i 且没有逗号的边界匹配原子的完全 i 匹配的序列。一个原子后跟一个包含一个整数 i 和一个逗号的边界,匹配一系列 i 或多个原子匹配。后跟包含两个整数 i 和 j 的边界的原子匹配原子的 i 到 j(包括)匹配的序列。

原子是包含在“()”中的正则表达式(匹配正则表达式的匹配)、空集“()”(匹配空字符串)(!)、括号表达式(见下文)、'。 ' (匹配任何单个字符)、'^'(匹配行首的空字符串)、'$'(匹配行尾的空字符串)、'\' 后跟字符之一“ ^.[$()|*+?{\" (匹配作为普通字符的那个字符),一个 '\' 后跟任何其他字符(!)(匹配作为普通字符的那个字符,就像 ' \' 不存在(!)),或没有其他意义的单个字符(匹配该字符)。一种 '{' 后面跟一个数字以外的字符是普通字符,而不是bound(!)的开头。以“\”结束 RE 是非法的。


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

关键问题在下一段:

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

你的情况是你有一个空的分支。正如您从“(!)”中看到的那样,空分支是一个开放或不可移植的问题。我认为这就是为什么它适用于某些系统但不适用于其他系统的原因。(我在 Cygwin 4.1.10(4)-release 上对其进行了测试,但它不起作用,然后在 Linux 3.2.25(1)-release 上测试它,它确实如此。这两个系统具有相同但不完全相同的手册页正则表达式7。

假设分支必须是非空的,那么一个分支可以是一个片段,也可以是一个原子。

原子可以是“一组空的“()”(匹配空字符串)(!)”。 <sarcasm>嗯,这真的很有帮助。</sarcasm> 因此,POSIX 为空字符串指定了一个正则表达式,即(),但还附加了一个“(!)”,表示这是一个开放的问题,或者不可移植。

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

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

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

但是,虽然(希望)这个建议在您当前的设置中对您有用,但不能保证它是可移植的。很抱歉让您失望了。

于 2012-06-18T11:45:56.237 回答
0

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

于 2012-05-24T18:54:56.747 回答