在R中的正则表达式替换中可以使用量词吗?

3
我的目标是用一个符号代替一个字符串,并重复该符号与字符串中相同数量的字符,类似于将字母替换为大写字母的\\U\\1。如果我的模式是"...(*)...",那么我对(*)捕获的内容的替换将类似于x\\q1{\\q1}x,因此我将得到与*所捕获的字符数量相同的x
这是否可能?我主要考虑使用sub,gsub方法,但您可以使用其他库,如stringi,stringr等来回答。您可以方便地使用perl = TRUEperl = FALSE和其他选项。
我假设答案可能是否定的,因为选择似乎很有限(?gsub)。
a replacement for matched pattern in sub and gsub. Coerced to character if possible. For fixed = FALSE this can include backreferences "\1" to "\9" to parenthesized subexpressions of pattern. For perl = TRUE only, it can also contain "\U" or "\L" to convert the rest of the replacement to upper or lower case and "\E" to end case conversion. If a character vector of length 2 or more is supplied, the first element is used with a warning. If NA, all elements in the result corresponding to matches will be set to NA. 

主要的量词符号是(?base::regex):

?

    The preceding item is optional and will be matched at most once.
*

    The preceding item will be matched zero or more times.
+

    The preceding item will be matched one or more times.
{n}

    The preceding item is matched exactly n times.
{n,}

    The preceding item is matched n or more times.
{n,m}

    The preceding item is matched at least n times, but not more than m times.

好的,但似乎这是一个选项(在PCRE中没有,不确定是否在PERL或其他地方有...)(*),它捕获了星号量词能够匹配的字符数(我在https://www.rexegg.com/regex-quantifier-capture.html找到了这个选项),因此可以使用\q1(同一参考资料)引用第一个捕获的量词(以及\q2等)。我还阅读到(*)等价于{0,},但我不确定这对我感兴趣的内容是否真实。

编辑更新

由于被评论者询问,我通过这个有趣问题提供了一个具体示例。 我稍微修改了一下例子。假设我们有字符串a <- "I hate extra spaces elephant",因此我们想要保留单词之间唯一的空格,每个单词的前5个字符(直到原始问题为止),但然后是每个其他字符的句点(不确定这是否是原始问题所期望的,但无关紧要),因此结果字符串将是"I hate extra space. eleph..."(对于spaces中的最后一个selephant末尾的三个字母ant,分别用一个.和3个.表示)。因此,我首先保留了前5个字符。

gsub("(?<!\\S)(\\S{5})\\S*", "\\1", a, perl = TRUE)
[1] "I hate extra space eleph"

我该如何用点号或其他符号替换\\S*中精确数量的字符?


如果您编辑一下问题,它会更好。我很感激您对此进行了研究,但在回答中引用帮助页面通常比在问题中引用更合适。只需简单地说“我已经在?base::regex中阅读了有关量词的内容,但没有找到有关在替换中使用它们的任何信息”即可。 - Gregor Thomas
@G.Grothendieck 我编辑了我的问题并提出了具体的问题。 - iago
@GregorThomas 感谢您在第一条评论中的回答。我不理解您的第二条评论。我已经更新了我的问题,并提供了一个具体的例子。 - iago
我的第二条评论试图表达的是,你实际的问题从“我的目标...”这一段开始。在到达重点之前大篇幅地复制/粘贴正则表达式帮助页面的内容并没有为你的问题增加有用的信息。相反,它通过掩盖要点使你的问题变得不太容易被人们发现,并且让人们更难将这个问题作为一个有用的资源。 - Gregor Thomas
我建议您编辑您的问题,删除“我的目标...”段落上面的所有内容,而是将其总结为“我希望我可以使用gsub等方法来实现这一点,但在阅读?base::regex中有关量词的信息时,我没有找到有关在替换中使用它们的任何内容。” - Gregor Thomas
显示剩余5条评论
2个回答

0

量词不能用于替换模式,也不能提供它们匹配多少个字符的信息。

你需要的是一个\G基本 PCRE 模式,以便在字符串中特定位置之后查找连续匹配项:

a <- "I hate extra spaces elephant"
gsub("(?:\\G(?!^)|(?<!\\S)\\S{5})\\K\\S", ".", a, perl = TRUE)

请查看R演示正则表达式演示

详情

  • (?:\G(?!^)|(?<!\S)\S{5}) - 上一个成功匹配的结尾或五个非空格字符,前面没有非空格字符
  • \K - 匹配重置运算符,丢弃到目前为止匹配的文本
  • \S - 任何非空白字符。

0

gsubfn类似于gsub,不同的是替换字符串可以是一个函数,该函数输入匹配内容并输出替换内容。该函数可以选择作为公式表达,如我们在这里用它来替换每个单词字符组成的字符串,并将其替换为该字符串的函数输出结果。不需要复杂的正则表达式。

library(gsubfn)

gsubfn("\\w+", ~ paste0(substr(x, 1, 5), strrep(".", max(0, nchar(x) - 5))), a)
## [1] "I hate extra space. eleph..."

或者几乎相同,只是函数略有不同:

gsubfn("\\w+", ~ paste0(substr(x, 1, 5), substring(gsub(".", ".", x), 6)), a)
## [1] "I hate extra space. eleph..."

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