我使用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
形式的带连字符的单词。
非常欢迎您的建议
答案 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破折号等,正则表达式开头和结尾的^
和$
表示这将是一个独立的字符。