西里尔字母的正则表达式问题
Reg Expressions Issues with Cyrillic letters
我过去在正则表达式和西里尔字母方面遇到过问题,所以我想知道我是否做错了什么?
这里有两个可重现的例子:
示例 1 - 前瞻和后视断言问题:
latin <- "city New York, Manhattan\n1st Avenue"
cyrilic <- "град Ню Йорк, Манхатън\n1во Авеню"
stringr::str_extract(latin, pattern = "(?<=city New York, )[\w\s]+(?=\n)")
#returns: Manhattan
stringr::str_extract(cyrilic, pattern = "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
stringr::str_extract(cyrilic, pattern = "(?<=град Ню Йорк, ).+(?=\n)")
#both return: NA
示例 2 - grep 的问题 ignore.case = TRUE:
randomWord <- "Човек"
grep(pattern = "човек", x = randomWord, ignore.case = T)
#returns: integer(0)
关于如何编写正则表达式以使其在西里尔字母中工作的任何想法?
我的默认文本编码是 UTF-8,这是我的会话信息:
> sessionInfo()
R version 3.3.3 (2017-03-06)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
locale:
[1] LC_COLLATE=Bulgarian_Bulgaria.1251 LC_CTYPE=Bulgarian_Bulgaria.1251
[3] LC_MONETARY=Bulgarian_Bulgaria.1251 LC_NUMERIC=C
[5] LC_TIME=Bulgarian_Bulgaria.1251
我不确定为什么在这种情况下 str_extract
returns NA
,因为看起来正则表达式是有效的。
但是 str_locate
和 str_detect
似乎按预期工作:
stringr::str_detect(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
#returns TRUE
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
#returns the start and end positions for Манхатън
您的问题的解决方法是结合使用 substr()
和 str_locate
:
substr(cyrilic,
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")[1],
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")[2]
)
#returns 'Манхатън'
问题可能出在 ICU 如何处理从 stringr str_extract
接收到的模式:看起来生成的后视模式不再是已知宽度。或者,str_extract
.
存在其他错误
在这种情况下,使用模式长度没有问题的 str_match
会更安全:
> str_match(cyrilic, pattern = "град Ню Йорк,\s*([\w\s]+)\n")[,2]
[1] "Манхатън"
只要访问正确的组,在这里,它是结果列表中的第二项。
至于您在 grep
中使用的 TRE 正则表达式,我还在不同环境中观察到各种问题。在我的 Windows 7 机器上,您的代码 returns 1
。但是,使用文字 Unicode 字母的 TRE 正则表达式可能会失败,最佳做法是使用 PCRE 正则表达式。为了使其完全识别 Unicode,不要忘记在模式开头添加 (*UCP)
PCRE 动词,以便 \w
、\d
等可以匹配所有 Unicode 字符。这里,没有必要and
> randomWord <- "Човек"
> grep(pattern = "човек", x = randomWord, ignore.case = T, perl=TRUE)
[1] 1
同样有效。
我过去在正则表达式和西里尔字母方面遇到过问题,所以我想知道我是否做错了什么?
这里有两个可重现的例子:
示例 1 - 前瞻和后视断言问题:
latin <- "city New York, Manhattan\n1st Avenue"
cyrilic <- "град Ню Йорк, Манхатън\n1во Авеню"
stringr::str_extract(latin, pattern = "(?<=city New York, )[\w\s]+(?=\n)")
#returns: Manhattan
stringr::str_extract(cyrilic, pattern = "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
stringr::str_extract(cyrilic, pattern = "(?<=град Ню Йорк, ).+(?=\n)")
#both return: NA
示例 2 - grep 的问题 ignore.case = TRUE:
randomWord <- "Човек"
grep(pattern = "човек", x = randomWord, ignore.case = T)
#returns: integer(0)
关于如何编写正则表达式以使其在西里尔字母中工作的任何想法?
我的默认文本编码是 UTF-8,这是我的会话信息:
> sessionInfo()
R version 3.3.3 (2017-03-06)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows >= 8 x64 (build 9200)
locale:
[1] LC_COLLATE=Bulgarian_Bulgaria.1251 LC_CTYPE=Bulgarian_Bulgaria.1251
[3] LC_MONETARY=Bulgarian_Bulgaria.1251 LC_NUMERIC=C
[5] LC_TIME=Bulgarian_Bulgaria.1251
我不确定为什么在这种情况下 str_extract
returns NA
,因为看起来正则表达式是有效的。
但是 str_locate
和 str_detect
似乎按预期工作:
stringr::str_detect(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
#returns TRUE
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")
#returns the start and end positions for Манхатън
您的问题的解决方法是结合使用 substr()
和 str_locate
:
substr(cyrilic,
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")[1],
stringr::str_locate(cyrilic, "(?<=град Ню Йорк, )[\w\s]+(?=\n)")[2]
)
#returns 'Манхатън'
问题可能出在 ICU 如何处理从 stringr str_extract
接收到的模式:看起来生成的后视模式不再是已知宽度。或者,str_extract
.
在这种情况下,使用模式长度没有问题的 str_match
会更安全:
> str_match(cyrilic, pattern = "град Ню Йорк,\s*([\w\s]+)\n")[,2]
[1] "Манхатън"
只要访问正确的组,在这里,它是结果列表中的第二项。
至于您在 grep
中使用的 TRE 正则表达式,我还在不同环境中观察到各种问题。在我的 Windows 7 机器上,您的代码 returns 1
。但是,使用文字 Unicode 字母的 TRE 正则表达式可能会失败,最佳做法是使用 PCRE 正则表达式。为了使其完全识别 Unicode,不要忘记在模式开头添加 (*UCP)
PCRE 动词,以便 \w
、\d
等可以匹配所有 Unicode 字符。这里,没有必要and
> randomWord <- "Човек"
> grep(pattern = "човек", x = randomWord, ignore.case = T, perl=TRUE)
[1] 1
同样有效。