在R中的反向引用

7

我对反向引用的使用感到非常困惑。

strings <- c("^ab", "ab", "abc", "abd", "abe", "ab 12")

gsub("(ab) 12", "\\1 34", strings)
[1] "^ab"   "ab"    "abc"   "abd"   "abe"   "ab 34"

gsub("(ab)12", "\\2 34", strings)
[1] "^ab"   "ab"    "abc"   "abd"   "abe"   "ab 12"

我知道 \1 指的是第一个子模式(从左向右读取),\2 指的是第二个子模式,以此类推。但是我不知道这些子模式具体意味着什么。为什么 \1 和 \2 会给出不同的输出。

gsub("(ab)", "\\1 34", strings)
[1] "^ab 34"   "ab 34"    "ab 34c"   "ab 34d"   "ab 34e"   "ab 34 12"

此外,为什么我在(ab)后面删除12后,它会得出这样的结果?
gsub("ab", "\\1 34", strings)
[1] "^ 34"   " 34"    " 34c"   " 34d"   " 34e"   " 34 12"

此外,如果ab没有括号,那么这表示什么?

我对反向引用真的一团糟,希望有人能清楚地解释一下其逻辑。


1
这不是“子模式”,而是捕获组。如果你在谷歌上搜索,你会找到很多资源。括号()内的任何模式都是捕获组。无论如何,在你的第一个例子中我得到的结果不同。最后一个元素是ab 34而不是ab 12 - nicola
是的,你说得对,我复制粘贴了一个错误的输出。 - Bratt Swan
1个回答

14
在第一和第二种情况下,有一个单一的捕获组,即使用(...)捕获的组,但是在第一种情况替换中,我们正确地使用了反向引用,即第一个捕获组,在第二种情况下,使用了\\2,但实际上从未存在过。
为了说明这一点。
gsub("(ab)(d)", "\\1 34", strings)
#[1] "^ab"   "ab"    "abc"   "ab 34" "abe"   "ab 12"

在这里,我们使用了两个捕获组((ab)(d)),在替换中我们首先有一个反向引用(\\1),后面跟着一个空格和34。因此,在“字符串”中,这将匹配第4个元素即“abd”,获取第一个反向引用(\\1)后面跟着一个空格和34的“ab”。

假设我们使用第二个反向引用

gsub("(ab)(d)", "\\2 34", strings)
#[1] "^ab"   "ab"    "abc"   "d 34"  "abe"   "ab 12"

第一个字符被移除,现在我们得到了“d”后面跟着一个空格和数字34。

假设我们使用的是一般情况而不是特定字符。

gsub("([a-z]+)\\s*(\\d+)", "\\1 34", strings)
#[1] "^ab"   "ab"    "abc"   "abd"   "abe"   "ab 34"
gsub("([a-z]+)\\s*(\\d+)", "\\2 34", strings)
#[1] "^ab"   "ab"    "abc"   "abd"   "abe"   "12 34"

注意在最后一个元素中,通过从第一个反向引用切换到第二个反向引用来更改值。使用的模式是一个或多个小写字母(在捕获组(([a-z]+))内),后跟零个或多个空格(\\s*),然后是第二个捕获组中的一个或多个数字((\\d+))(这仅与“strings”的最后一个元素匹配)。在替换中,我们使用上述第一个和第二个反向引用。


这样更有意义。但是我仍然对 gsub("([a-z]+)\\s*(\\d+)", "\\2 34", strings) 感到困惑。正如你所说,它匹配了 "ab 12",并且你使用 \2 来捕获第二个组。对我来说,它的含义是当你捕获一个组时,该组将被固定,因此 "ab 12" 将被替换为 "34 12" 而不是 "12 34"。 - Bratt Swan
1
在这个例子中,我将使用第二个捕获组即(\\d+)进行替换,因此它会返回12。由于我们还要创建一个空格,然后是34,所以结果将是"12 34"。如果你想要得到"34 12",那么正则表达式应该是"34 \\2" - akrun

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