在R中,为了从字符串中删除标点符号,我可以这样做:
x <- 'a#,g:?s!*$t/{u}\d\&y'
gsub('[[:punct:]]','',x)
[1] "agstudy"
这很聪明,但我没有严格控制删除的标点符号(想象一下我想在我的角色中保留一些符号)。如何在不忘记任何符号的情况下以更明确的方式重写此gsub
,如下所示:
gsub('[#,:?!*$/{}\\&]','',x,perl=FALSE)
修改
我遇到的困难是如何编写正则表达式(我更喜欢在R中)从x中删除所有标点符号,并仅保留#例如:
"a#gstudy"
答案 0 :(得分:8)
使用否定先行断言:
x <- 'a#,g:?s!*$t/{u}\\d\\&y'
gsub('(?!#)[[:punct:]]','',x, perl=TRUE)
# [1] "a#gstudy"
这实质上是对每个字符进行两次测试,从前面的字符间空间询问一次下一个字符是否是"#"
以外的字符,然后从字符本身询问它是否是标点符号。如果两个测试都为真,则会注册匹配并删除该字符。
答案 1 :(得分:7)
您可以使用否定的字符类,例如:
\pP
是标点字符的unicode字符类。
\PP
就是不是标点字符。
[^\PP]
就是标点符号。
[^\PP~]
就是一个标点字符。
注意:您可以使用\p{PosixPunct}
:
[^\P{PosixPunct}~]
或在\p{XPosixPunct}
的ASCII范围内使用具有此特殊性的unicode标点字符:
[^\P{XPosixPunct}~]
答案 2 :(得分:5)
阅读this page表示[[:punct:]]
字符应包括:
[-!"#$%&'()*+,./:;<=>?@[\\\]^_`{|}~]
在R ?regex
页面上,我们也将此作为验证:
[:punct:]
Punctuation characters:
! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
因此,您可以将其作为创建自己模式的基础,不包括您想要保留的字符。
这很麻烦,特别是有两个更好的答案,但我只是想表现出我心中的愚蠢:
创建一个如下所示的函数:
newPunks <- function(CHARS) {
punks <- c("!", "\\\"", "#", "\\$", "%", "&", "'", "\\(", "\\)",
"\\*", "\\+", ",", "-", "\\.", "/", ":", ";", "<",
"=", ">", "\\?", "@", "\\[", "\\\\", "\\]", "\\^", "_",
"`", "\\{", "\\|", "\\}", "~")
keepers <- strsplit(CHARS, "")[[1]]
keepers <- ifelse(keepers %in% c("\"", "$", "{", "}", "(", ")",
"*", "+", ".", "?", "[", "]",
"^", "|", "\\"), paste0("\\", keepers), keepers)
paste(setdiff(punks, keepers), collapse="|")
}
用法:
gsub(newPunks("#"), "", x)
# [1] "a#gstudy"
gsub(newPunks(""), "", x)
# [1] "agstudy"
gsub(newPunks("&#{"), "", x)
# [1] "a#gst{ud&y"
Bleah。我上床睡觉的时间......
答案 3 :(得分:3)
它在Perl中完全相同,[:punct:]
是一个简单映射到的POSIX字符类:
[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{|}~]
等效的Perl版本将是:
my $x = 'a#,g:?s!*$t/{u}\d\&y';
$x =~ s/[[:punct:]]//g;
print $x;
__END__
agstudy
答案 4 :(得分:3)
直截了当的方法是使用前瞻或后视来匹配相同的角色两次,一次确保它是一个punction,一次确保它不是“#
”。
(?=[^#])[[:punct:]]
或
(?!#)[[:punct:]]
但是,前瞻和外观看起来有点贵。我们不是在每个位置都使用一个环视,而是在找到标点时使用一个更有效率。
[[:punct:]](?<!#)
当然,完全摆脱外观会更有效率。这可以通过双重否定来实现。
[^[:^punct:]#]
我没有用R测试这些,但它们至少应该与perl=TRUE
一起使用。