我正在尝试清理存储在R Data Frame列中的一些小字符串(1-3个字母)。具体来说,假设下一个R脚本:
df = data.frame( "original" = c("ABCDE FG H",
"IJKL MN OPQRS",
"TUV WX YZ AAAA"))
df$filter1 = gsub("(^|\\s)[A-Z]{1,2}($|\\s)", " ", df$original)
df$filter2 = gsub("\\b[A-Z]{1,2}\\b", " ", df$original)
> df
original | filter1 | filter2 |
1 ABCDE FG H | ABCDE H | ABCDE |
2 IJKL MN OPQRS | IJKL OPQRS | IJKL OPQRS|
3 TUV WX YZ AAAA | TUV YZ AAAA| TUV AAAA |
我不明白为什么第一个过滤器(^|\\s)[A-Z]{1,2}($|\\s)
不能替代" H"在第一行或" YZ"在第三个。我希望使用\\b[A-Z]{1,2}\\b
作为过滤器(filter2列)的结果相同。请不要担心多个空格,这对我来说并不重要(除非这是问题所在:)。)
我认为问题在于"全球性"操作,它是否,如果它发现第一个没有替换第二个,但如果我做下一个替换它不是真的:
> gsub("A", "X", "AAAABBBBCCCDDDDAAAAAAAEEE")
[1] "XXXXBBBBCCCDDDDXXXXXXXEEE"
那么,为什么结果不同?
答案 0 :(得分:3)
关键是Handler BobId
只能匹配非重叠的字符串。 gsub
是第一个预期匹配, FG
是第二个,您可以看到这些字符串重叠,因此, H
消耗"(^|\\s)[A-Z]{1,2}($|\\s)"
之后的尾随空格{1}},FG
与模式不匹配。
看:从左到右分析H
。表达式与ABCDE FG H
匹配,正则表达式索引在 FG
之前。只有这封信匹配,但H
需要一个空格或字符串的开头 - 此位置没有。
To" fix"这个和使用相同的逻辑,您可以使用PCRE正则表达式(^|\s)
与 lookarunds :
gsub
或
df$filter1 = gsub("(^|\\s)[A-Z]{1,2}(?=$|\\s)", " ", df$original, perl=TRUE)
如果您需要实际使用(删除)空格,只需在(或/和之后)之前添加df$filter1 = gsub("(?<!\\S)[A-Z]{1,2}(?!\\S)", " ", df$original, perl=TRUE)
。
第二个表达式\\s*
包含单词边界,它们是不使用文本的零宽度断言,因此,正则空间引擎可以匹配"\\b[A-Z]{1,2}\\b"
和FG
,因为空格不被消耗。