regex - 在 R 中分解 PascalCase

标签 regex r

我有一系列使用 PascalCase 的字符串。

"BobDylan"
"MikhailGorbachev" 
"HelpfulStackOverflowPeople"

我想要一个 R 中的函数,它将在每个单词之间放置空格。我已经用像 perl 的正则表达式和 gsub( ) 实现了这一点。功能。本质上,我在不是字符串第一个字母的每个大写字母之前放置一个空格。
gsub("(?!^)(?=[A-Z])", " ","BobDylan",perl=TRUE)
[1] "Bob Dylan"

但是,我的列表中的某些单词可能有大写的缩写,我不想用空格分隔。
"BobDylanUSA"
"MikhailGorbachevUSSR" 
"HelpfulStackOverflowPeople"

应用与之前相同的语法将在每个大写字母之间创建空格。
gsub("(?!^)(?=[A-Z])", " ","MikhailGorbachevUSSR",perl=TRUE)
[1] "Mikhail Gorbachev U S S R"

但是,我希望缩写保持不变。所需的输出如下所示。
[1] "Bob Dylan USA"
[1] "Mikhail Gorbachev USSR"
[1] "Helpful Stack Overflow People"

在我的 gsub( ) 中我还需要做什么?表达?或者,是否有更好的方法来完全解决这个问题。

最佳答案

您可以稍微修改自己的正则表达式:将前瞻转换为捕获组并添加 + [A-Z] 后面的量词字符类,使其匹配 1+ 个字符:

> v <- c("BobDylan","MikhailGorbachev","HelpfulStackOverflowPeople","BobDylanUSA","MikhailGorbachevUSSR","HelpfulStackOverflowPeople")
> gsub("(?<!^|\\s)([A-Z]+)", " \\1", v, perl=T)
[1] "Bob Dylan"                     "Mikhail Gorbachev"            
[3] "Helpful Stack Overflow People" "Bob Dylan USA"                
[5] "Mikhail Gorbachev USSR"        "Helpful Stack Overflow People"

它仍然是一个 PCRE 正则表达式,因为您不想在字符串的开头添加一个空格(这是通过查看 (?<!^) 此处阻止的,并且仅当大写字母之前没有空格时。

看到这个 regex demo

非 PCRE 替代品

如果您想尝试使用 TRE(非 PCRE)正则表达式
> gsub("(\\S)([A-Z]+)", "\\1 \\2", v)
[1] "Bob Dylan"                     "Mikhail Gorbachev"            
[3] "Helpful Stack Overflow People" "Bob Dylan USA"                
[5] "Mikhail Gorbachev USSR"        "Helpful Stack Overflow People"

这是 another regex demo .

在这里,该模式匹配并捕获具有 (\\S) 的任何一个非空白字符。接着是 1+ 个大写 ASCII 字母捕获到组 2 中(参见 ([A-Z]+)),然后我们使用 \\1\\2 numbered backreferences在替换模式中,在这些捕获的子值之间添加一个空格。

我尝试拆分一个单词的大写字母

由于单字母单词只能匹配一次,我们需要能够匹配它们前后的位置,这需要使用环视,因为只有环视允许通过执行所谓的零宽度断言来“重叠”匹配检查当前位置之前(lookbehinds)和之后(lookaheads)的文本。因此,只有 PCRE 正则表达式可以处理 .

也就是说,任何一种解决方案都会产生相同的结果:
(?|([a-z])(?=[A-Z])|([A-Z]+)(?=[A-Z][a-z]))

this regex demo .

单字字母问题仍将存在在大写缩写后 (见 Mail Sent To USAA Day Ago)。那你就需要查字典了。
> v <- c("BobDylan","MikhailGorbachev","BobDylanUSA","MikhailGorbachevUSSR","HelpfulStackOverflowPeople","IAmATallDrinkOfWater","MailSentToUSAADayAgo")
> gsub("(?|([a-z])(?=[A-Z])|([A-Z]+)(?=[A-Z][a-z]))", "\\1 ", v, perl=T)
[1] "Bob Dylan"                     "Mikhail Gorbachev"            
[3] "Bob Dylan USA"                 "Mikhail Gorbachev USSR"       
[5] "Helpful Stack Overflow People" "I Am A Tall Drink Of Water"   
[7] "Mail Sent To USAA Day Ago"    

由于 branch reset,模式将匹配并捕获模式内的两个捕获组并将其捕获到组 1 中。 ( (?|...|...) )。捕获的文本通过反向引用插入回,然后添加一个空格。
  • ([a-z])(?=[A-Z]) - 在一个小写字母后跟一个大写字母
  • ([A-Z]+)(?=[A-Z][a-z]) - 在 1+ 个大写字母后跟 1 个大写字母,然后是 1 个小写字母。
  • 关于regex - 在 R 中分解 PascalCase,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36778221/

    相关文章:

    r - 在 R 数据框中查找整行?

    Python 使用正则表达式重命名文件

    regex - Wiremock url 匹配 - "null. When using a regex, "?"should be "\\?". URLs must start with a/"

    javascript - detectmobilebrowser.js 的正则表达式有魔法吗?

    python - gCentroid (rgeos) R 与实际质心(Python 中)

    r - rstudio中是否可以使用renjin

    java - 匹配电子邮件的 RegEx 也匹配 URL

    正则表达式问题 - 在句子中查找类似密码的单词

    python - 如何在Keras R中提取VGG16的top-K层

    r - 如何优雅地用不同的向量替换重复的值?