我有一系列使用 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/