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

Sua*_*uan 7 regex bash

我在(t|b|bug_|task_|)1234使用bash正则表达式捕获此格式的字符串中的数字时遇到问题.以下不起作用:

[[ $current_branch =~ ^(t|b|bug_|task_|)([0-9]+) ]]
Run Code Online (Sandbox Code Playgroud)

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

[[ $current_branch =~ ^(t|b|bug_|task_)([0-9]+) ]]
Run Code Online (Sandbox Code Playgroud)

它有效,但当然是错误的,因为它没有涵盖没有前缀的情况.我知道在这种情况下我能做到

[[ $current_branch =~ ^(t|b|bug_|task_)?([0-9]+) ]]
Run Code Online (Sandbox Code Playgroud)

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

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

JXG*_*JXG 4

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


POSIX.2 中定义的正则表达式(“RE”)有两种形式:现代 RE(大致为 egrep;POSIX.2 称这些“扩展”RE)和过时的 RE(大致为 ed(1) 的 RE) ; POSIX.2“基本”RE)。过时的 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(含)匹配序列相匹配。

原子是用“()”括起来的正则表达式(匹配正则表达式的匹配项)、“()”的空集(匹配空字符串)(!)、括号表达式(见下文)、'. ' (匹配任意单个字符)、'^'(匹配行首的空字符串)、'$'(匹配行尾的空字符串)、'\' 后跟一个字符 " ^.[$()|*+?{\"(匹配作为普通字符的该字符),一个 '\' 后跟任何其他字符(!)(匹配作为普通字符的该字符,就好像 ' \' 不存在(!)),或没有其他意义的单个字符(与该字符匹配)。'{' 后跟数字以外的字符是普通字符,而不是边界 (!) 的开头。以“\”结束 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]+) ]]
Run Code Online (Sandbox Code Playgroud)

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

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