R:删除用拉丁语以外的字母写的字(但包括变音符号)

时间:2016-11-26 01:06:15

标签: r regex

我想根据地理名称数据库搜索意大利地理实体的文本,我可以用

下载
download.file('http://download.geonames.org/export/dump/IT.zip', destfile = 'IT.zip')
unzip('IT.zip', exdir = 'IT')
require(readr)
it_gn <- read_delim("IT/IT.txt", "\t", escape_double = FALSE, col_names = FALSE, trim_ws = TRUE)

X4包含地理名称的替代版本,包括其他语言的版本。

例如

it_gn$X4[it_gn$X1 == 2522713]
# [1] "Vittoira,Vittoria,vu~ittoria,ヴィットーリア"

由于我搜索的文件是意大利语,我想删除用拉丁字母以外的字母表编写的所有名称,但包括意大利语中使用的变音符号:-à , -è , -é , -ì , -ò , -ù以及-á , -í , -ó , -ú(这些都是正式用于意大利语,但它们可能会出现)。但目前尚不清楚我应该使用哪种正则表达式来识别非拉丁字母。

我尝试应用this回答,但正则表达式似乎没有任何区别......

grepl('[^\\x00-\\x7F]', 'ヴィットーリア')
# [1] TRUE

grepl('[^\\x00-\\x7F]', 'Vittoria')
# [1] TRUE

2 个答案:

答案 0 :(得分:4)

首先,你的正则表达式不起作用的原因是正则表达式转义符“\ xNN”是一个Perl扩展名,所以如果你想使用它,你需要传递“perl = TRUE”:

> grepl('[^\\x00-\\x7F]', 'ヴィットーリア', perl=TRUE)
[1] TRUE
> grepl('[^\\x00-\\x7F]', 'Vittoria', perl=TRUE)
[1] FALSE
>

(令人困惑的是,以下内容将起作用:

> grepl('[^\x01-\x7F]', 'ヴィットーリア')
[1] TRUE
> grepl('[^\x01-\x7F]', 'Vittoria')
[1] FALSE
>

因为没有双反斜杠,你使用R字符串文字转义序列“\ xNN”而不是上面的正则表达式转义序列;无论编码如何,这都会直接在字符串中嵌入给定的字节,这是非常糟糕的做法,所以我在这里避免使用它。)

话虽这么说,我认为最可读的方法是在你的R代码中包含Unicode字符:

isinvalid <- grepl('[^[:ascii:]àèéìòùáíóú]', name,
                   perl=TRUE, ignore.case=TRUE)

perl=TRUE允许您使用[:ascii:]尽管丑陋但似乎比其他选项更具可读性,如果您想要重音字符的大写版本,ignore.case=TRUE是必需的也被视为有效。

如果您的环境过于紧张,无法在源代码中包含Unicode,那么您可以使用普通的“\ u”转义来包含它们:

isinvalid <- grepl('[^[:ascii:]\ue0\ue8\ue9\uec\uf2\uf9\ue1\ued\uf3\ufa]', name,
                   perl=TRUE, ignore.case=TRUE)

请注意,您应该使用“\ u”转义符,而不是“\ x”转义符。这些是unicode代码点,而不是直接插入字符串的字节。 (再次,相当奇怪的是,你也可以使用\\x转义,利用Perl扩展,因为 - 相当莫名其妙 - Perl正则表达式“\ x”转义更像是R的字符串文字“\ u”转义而不是它的“\ x”逃脱。

呃...无论如何,我希望额外的解释能使更多明确而不是更少。

答案 1 :(得分:0)

在角色类的第一个位置使用插入符号否定它,这不是你想要的。看到这个差异:

> grepl('[\\x00-\\x7F]', 'ヴィットーリア')
[1] FALSE
> 
>  grepl('[\\x00-\\x7F]', 'Vittoria')
[1] TRUE

更符合您的需求:

> sapply( strsplit( 'ヴィットーリア', ""), grepl, patt='[\\x00-\\x7F]')
      [,1]
[1,] FALSE
[2,] FALSE
[3,] FALSE
[4,] FALSE
[5,] FALSE
[6,] FALSE
[7,] FALSE

由于我不理解的原因,我需要使用更长的patt参数来匹配小写ASCII:

patt='[A-Za-z\\x00-\\x7F]'

而且对于你的进一步观点,我需要明确地包含一串那些变音符号。

> sapply( c('à' , 'è' , 'é' , 'ì' , 'ò' , 'ù' ,  'á' , 'í' , 'ó' , 'ú'), grepl, patt='[A-Za-z\\x00-\\x7F]')
    à     è     é     ì     ò     ù     á     í     ó     ú 
FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE FALSE 

所以你可以试试:

patt = "[A-Za-zàèéìòùáíóú]"

并决定是否要排除换行符和标签。