正则表达式对英语和俄语的结果不同

3

那么,我有这个正则表达式:

[ ]{1}[^\w]*(шесть)[^\w]*[ ]{1}

还有一种变体:

[ ]{1}[^\w]*(conservation)[^\w]*[ ]{1}

我使用这段文本here来进行测试:

"""可能是每两个部门之间一个,而且他们有十多个。 很奇怪,每个人每周工作六小时吗?很明显,没有人工作, 否则自己的主管就不会接受。但是节约一些诊断费用难道不好吗?"""

"""1901年9月麦金利总统遭暗杀后,42岁的罗斯福成为美国历史上最年轻的总统。带领他的政党和国家进入进步时代,他提倡“平方交易”国内政策,承诺为普通公民提供公正、打破垄断、监管铁路以及纯净的食品和药物。他将保护环境置于优先位置,建立了无数新的六个国家公园、森林和纪念碑,旨在保护国家的自然资源。在外交政策上,他专注于中美洲,在那里开始修建巴拿马运河。他大大扩展了美国海军,并派遣大白舰队环游世界,展示美国在全球范围内的海军实力。他成功地结束了俄日战争,赢得了1906年的诺贝尔和平奖。"""

两段文本都是我随机找到的。但这不是重点。
当使用第一个正则表达式时,会得到以下匹配结果:

可能是每两个部门之间一个,而且他们有十多个。很奇怪,每个 人每周工作六小时吗?很明显,没有人工作, 否则自己的主管就不会接受。但是节约一些诊断费用难道不好吗?

这在第一块俄语文本中。
在第二个文本中,它只匹配

六个

匹配的上下文为

...新的六个国家公园...

如果我使用英语单词(例如"conservation"),那么它只会匹配英语文本中的该单词。
如果我将其添加到俄语文本中,比如这样:

...六个保护区的时间...

它将与“六个”相同的大块文本匹配。
为什么会发生这种情况?是因为文本是俄语吗?
我不完全确定这个正则表达式的作用,但在英语文本中,它会找到括号中的单词。我认为它对其他语言也是如此。

虽然这并不重要,但是我使用Python 2.7的re2库进行操作。然而,由于我在网上获得了相同的结果,因此我认为问题要么出在我对正则表达式的理解上,要么是与非英语文本有关。

谢谢!

编辑1:

代码如下:

source = the_text_above
term = "шесть"
expression = regex_builder(term) # This returns the regex I posted
compiled_pattern = re2.compile(expression, re2.IGNORECASE, re2.U) # This raises an error: RegexError: pattern too large - compile failed
compiled_pattern.search(source).span() # This returns the start and end of the chunk of text I mentioned.

附加说明 EDIT 1: 当我不使用re2.U时,文本块被返回。

编辑2:

我也尝试过:

compiled_pattern = re.compile(expression, re.U)

我得到了相同的结果。
编辑3 - 已解决:
因此,我尝试再次编译,同时使用re2.IGNORECASE和re2.U标志,并且它起作用了。
现在我的代码如下:
source = the_text_above
term = "шесть"
expression = regex_builder(term)
compiled_pattern = re2.compile(expression, re2.IGNORECASE | re2.U)
compiled_pattern.search(source).span()

它的工作方式如下。

1
请编写您的Python代码。您是如何使用正则表达式并展示输出结果的? - tglaria
1
如果使用了re.U标识符,\w将匹配俄文字母,而\W(如你的[^\w])将不再匹配西里尔字母。请参见 此演示 - Wiktor Stribiżew
我添加了标志,但现在出现了这个错误:RegexError:模式太大 - 编译失败 --- 我正在使用re2,我也会尝试使用常规的re。 - RandomGuyqwert
@stribizhev 我已经尝试过了,但是没有效果。它仍然返回单词周围的大块文本。 - RandomGuyqwert
@stribizhev 不,你一开始就是对的,应该使用re2.U标志。问题在于我使用了re2.compile( ..., re2.I , re2.U)而不是re2.compile(..., re2.I | re2.U ),这导致了一个错误,因此re2.U没有起到作用。 - RandomGuyqwert
显示剩余4条评论
2个回答

2
在RE2中,如果您不指定re2.U标志,则\w仅匹配ASCII字母:

\w 单词字符(≡ [0-9A-Za-z_]

因此,[^\w]匹配Cyrillic字母。
所以,您需要使用re2.U标志。
由于您将re2.Ire2.U组合使用,因此需要在它们之间使用按位OR(|)。
re2.compile(<YOUR_PATTERN>, re2.I | re2.U) 

0

我在使用Python 2.7.10和re模块时没有出现任何错误:

import re
txt_ru = u"""Наверное, по одному на пару отделений, а их больше десяти. Интересно, каждый работает по шесть часов в неделю? Работать, очевидно, некому, раз принимают сами заведующие. Но неужели экономия на нескольких диагностах"""
txt_en = u"""regulation of railroads, and pure food and drugs. Making conservation a top priority, he established myriad new шесть national parks, forests,"""
expression = u"[ ]{1}[^\w]*(шесть)[^\w]*[ ]{1}"
m_ru = re.search(expression, txt_ru, re.UNICODE)
m_en = re.search(expression, txt_en, re.UNICODE)

输出:

In [166]: print m_ru.group(0)
 шесть 

In [167]: print m_en.group(0)
 шесть 

1
是的,使用 re 库时,需要使用 re.Ure.UNICODE 使 \w 匹配 Unicode 字母。然而,OP 使用的是 RE2 库,问题在于 2 个标志的组合。 - Wiktor Stribiżew

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接