分组捕获单词边界

分组捕获单词边界

下面我将向标准输入发出正则表达式(a\b) \1grep插入几个测试字符串。

$ grep -E '(a\b) \1'

ab

粗体部分表示存在匹配。第二个,a ab难倒了我。捕获组可以用文字描述为“a后面跟着单词边界的字符”。

处理字符串 时a ab,正则表达式引擎匹配字符a,看到它后面跟着的不是“单词字符”,因此匹配\b。然后它匹配一个空格。到目前为止,一切都很好。

但是,它应该检查 if \1matches ab,据我所知它不应该,因为接下来a我们ab有一个单词字符。我不明白这是怎么回事!


接受答案后,我意识到我实际上仍然不明白发生了什么事。从上面的例子出发:

$ cat tests
a bab
a ba
a ab
$ grep -E '(\ba\b) \1' tests
a ab

这告诉我捕获组包括除字符串右边缘的单词边界之外的所有内容,我仍然不明白。

答案1

问题是\1指匹配的文本,不是一个正则表达式。在我们的例子中,匹配的文本是字符a。由于\1是文本,而不是正则表达式,因此它不关心a.观察:

$ cat file
a a
a ab
$ grep -E '(a\b) \1' file
a a
a ab

如果我们想\1成为一个单词,请为其添加一个单词边界:

$ grep -E '(a\b) \1\b' file
a a

因为\1\b后需要一个字边界\1,所以第二行不再匹配。

为了证明这\1不是正则表达式,让我们尝试:

$ echo '.a' | grep -E '(.)\1'
$ 

但:

$ echo '..' | grep -E '(.)\1'
..
$ 

因此,\1匹配..虽然.通常是正则表达式活动的并且匹配任何字符,\1但仅匹配句点。

文档

来自GNU grep 手册:

反向引用 '\n',其中 n 是单个数字,匹配之前匹配的子串由正则表达式的第 n 个带括号的子表达式。例如,“(a)\1”匹配“aa”。当与交替一起使用时,如果该组不参加比赛,则反向引用会使整个比赛失败。例如,“a(.)|b\1”将不匹配“ba”。当用 -e 或文件('-f file')给出多个正则表达式时,反向引用对于每个表达式都是本地的。 [强调。]

相关内容