用于排除R

时间:2015-07-10 23:28:54

标签: regex r

我使用R来标记一组文本;在标记化之后,我最终得到一个char矢量,其中保留了标点符号,撇号和连字符。例如,我有这个原始文本

txt <- "this ain't a Hewlett-Packard box - it's an Apple box, a very nice one!"

在标记化之后(我使用包scan_tokenizer中的tm执行)我得到以下字符向量

   > vec1
 [1] "this"            "ain't"           "a"               "Hewlett-Packard"
 [5] "box"             "-"               "it's"            "an"             
 [9] "Apple"           "box,"            "a"               "very"           
[13] "nice"            "one!"           

现在为了摆脱标点符号,我做了以下

vec2 <- gsub("[^[:alnum:][:space:]']", "", vec1)

这是,我用“”替换不是字母数字值,空格和撇号的所有内容;不过这是结果

> vec2
 [1] "this"           "ain't"          "a"              "HewlettPackard" "box"           
 [6] ""               "it's"           "an"             "Apple"          "box"           
[11] "a"              "very"           "nice"           "one"    

我想保留连字符sych为“Hewlett-Pacakard”,同时摆脱单独的连字符。基本上我需要一个正则表达式来排除vec2的\w-\w表达式中gsub形式的带连字符的单词。

非常欢迎您的建议

6 个答案:

答案 0 :(得分:5)

如果您只想删除“纯连字符”,请使用模式'^-$'(因为连字符不是正则表达式元字符。

vec2 <- vec1[!grepl( '^-$' , vec1) ]

如果你想删除“所有种类的裸体标点符号”,可能是:

vec2 <- vec1[!grepl( '^[[:punct:]]$' , vec1) ]

答案 1 :(得分:2)

strsplit(gsub('[[:punct:]](?!\\w)', '', txt, perl=T), ' ')[[1]]
 #[1] "this"            "ain't"           "a"              
 #[4] "Hewlett-Packard" "box"             ""               
 #[7] "it's"            "an"              "Apple"          
#[10] "box"             "a"               "very"           
#[13] "nice"            "one"

或者你可以这样做,以便在&#34; one&#34;:

之后保留感叹号
strsplit(gsub('(?<!\\w)[[:punct:]](?!\\w)', '', txt,perl=T), ' ')[[1]]
#  [1] "this"            "ain't"           "a"              
#  [4] "Hewlett-Packard" "box"             ""               
#  [7] "it's"            "an"              "Apple"          
# [10] "box,"            "a"               "very"           
# [13] "nice"            "one!"

我正在使用正则表达式的lookbehinds和lookaheads。模式(?!\\w)是一个先行(更确切地说,是一个负前瞻),并告诉评估者删除所有标点符号,除了后面跟着字母或数字的标点符号。在第二种模式中,(?<!\\w)被认为是负面的背后。除了字母或数字后面的标点符号外,它将删除所有标点符号。为了帮助记住差异,一个外观的外观&#34;返回&#34;在下一个标记处,前瞻看起来&#34; up&#34;在它之前发生的事情。

答案 2 :(得分:2)

strsplit(gsub("[^[:alnum:][:space:]'-]", "", txt), '\\s|\\ - ')

答案 3 :(得分:2)

你可以试试这个,

> library(stringr)    
> txt <- "this ain't a Hewlett-Packard box - it's an Apple box, a very nice one!"
> gsub("(?!\\b['-]\\b|\\s)[\\W_]", "", str_extract_all(txt, "\\S+")[[1]], perl=T)
 [1] "this"            "ain't"           "a"              
 [4] "Hewlett-Packard" "box"             ""               
 [7] "it's"            "an"              "Apple"          
[10] "box"             "a"               "very"           
[13] "nice"            "one"  

> strsplit(gsub('(?!\\b[[:punct:]]\\b|\\s)[\\W_]', '', txt,perl=T), ' ')[[1]]
 [1] "this"            "ain't"           "a"              
 [4] "Hewlett-Packard" "box"             ""               
 [7] "it's"            "an"              "Apple"          
[10] "box"             "a"               "very"           
[13] "nice"            "one" 

答案 4 :(得分:2)

以下是使用带有字边界(strsplit)的\b和非字字符(\W等同于[^[:alnum:]_])的方法

strsplit(txt, "\\b | \\b|\\W |\\W$")
#[[1]]
# [1] "this"            "ain't"           "a"               "Hewlett-Packard"
# [5] "box"             ""                "it's"            "an"             
# [9] "Apple"           "box"             "a"               "very"           
#[13] "nice"            "one"            

或者根本没有为单个连字符而不是""返回任何内容。

strsplit(txt, "\\b | \\b| ?\\W |\\W$")
#[[1]]
# [1] "this"            "ain't"           "a"               "Hewlett-Packard"
# [5] "box"             "it's"            "an"              "Apple"          
# [9] "box"             "a"               "very"            "nice"
#[13] "one"

答案 5 :(得分:1)

我建议两种方法,首先,尽可能保持简单,其次,尽可能使用Unicode字符类,尤其是对于各种文本处理器可能替换其他字符的连字符(例如参见{{3}) })。

所以:

最简单(也非常快),只检测连字符的二进制匹配:

vec1[!(vec1 %in% "-")]

更好(从Unicode角度来看),也非常快:

vec1[!stringi::stri_detect_regex(vec1, "^\\p{Pd}$")]

最后一个使用Unicode字符类Pd,表示&#34;短划线或连字符标点符号&#34;。这包括非断开连字符,em破折号等,正则表达式开头和结尾的^$表示这将是一个独立的字符。