4

我对正则表达式相当有经验,但是在当前涉及析取的应用程序中遇到了一些困难。

我的情况是这样的:我需要根据地址的“标识符元素”上的正则表达式匹配将地址分成其组成部分——类似的英文示例是“state”、“road”或“林荫大道”--例如,如果我们在地址中写下了这些。想象一下,我们有一个像下面这样的地址,其中(这在英语中永远不会发生),我们在每个名称之后指定了标识符类型

United States COUNTRY California STATE San Francisco CITY Mission STREET 345 NUMBER

(大写字母中的词是我所说的“标识符”)。

我们想把它解析成:
United States COUNTRY
California STATE
San Francisco CITY
Mission STREET
245 NUMBER

好的,这当然是为英语设计的,但有一个问题:我正在处理中文数据,实际上这种标识符规范一直在发生。下面的一个例子:

云南-省 ; 丽江-市 ; 古城-区 ; 西安-街 ; 杨春-巷 ; Yunnan-Province ; LiJiang-City ; GuCheng-District ; Xi'An-Street ; Yangchun-Alley

这很容易——对潜在的候选标识符名称进行惰性匹配,分成一个分离列表。

对于中国,以下是“省级”实体:

省 (Province) , 自治区 (Autonomous Region) , 市 (Municipality)

所以到目前为止我的正则表达式看起来像这样:

(.+?(?:(?:省)|(?:自治区)|(?:市)))

我有一系列这些,以说明地址的不同部分。例如,对应于城市的下一个级别是:

(.+?(?:(?:地区)|(?:自治州)|(?:市)|(?:盟)))

所以要匹配一个省实体,然后是一个城市实体:

(.+?(?:(?:省)|(?:自治区)|(?:市)))(.+?(?:(?:地区)|(?:自治州)|(?:市)|(?:盟)))

使用命名的捕获组:
(?<Province>.+?(?:(?:省)|(?:自治区)|(?:市)))(?<City>.+?(?:(?:地区)|(?:自治州)|(?:市)|(?:盟)))

对于上述情况,这会产生:
$+{Province} = 云南省<br> $+{City} = 丽江市

这一切都很好,让我走得很远。然而,问题是当我尝试考虑可能是其他标识符的子字符串的标识符时。例如,一个常见的街道实体是“村委会”,意思是村组委会。在我希望分开的一组地址中,并非每个地址都完整地写出。事实上,我找到了“村委”,也只是简单的“村”。

问题?如果我对这些元素进行纯析取,我们有以下内容:

(?<Street>.+?(?:(?:村委会)|(?:村委)|(?:村)))

然而,如果你有一个实体保定-村委会(保定村组委会),这个懒惰的正则表达式会在村停下来收工,让我们可怜的委员会成为孤儿,因为村是潜在的分离元素之一.

想象一下这样的英语等价物:
(?<Animal>.+?(?:(?:Cat)|(?:Elephant)|(?:CatElephant)|(?:City)))

我们有两个输入字符串:
1.“crap catelephant crap city”,我们想要“Crap catelephant”和“crap city” 2.“crap catelephant city”,我们想要“crap cat”“elephant city”

啊,你说的解决办法就是让前置标识符贪婪捕获。但!有些实体具有相同的标识符但不在同一级别。

以市为例。这意味着简单的“城市”。但在中国,有县级市、省级市和市级市。如果该字符在字符串中出现两次,尤其是在两个相邻实体中,贪心搜索会错误地将贪心匹配标记为第一个实体。如下所示:

广东-省 ; 江门-市 ; 开平-市 ; 三埠-区 石海管-区<br> Guangdong-province ; Jiangmen-City ; Kaiping-City ; Sanbu-District ; Shihaiguan-District

(请注意,如上所述,这是手动分割的。原始数据将仅包含一串连接的字符)

贪婪搜索的匹配是
江门市开平市

这是错误的,因为两个相邻的实体应该被分成它们的组成部分。一个是省级市,一个是县级市。

回到原点,感谢您阅读本文,有没有办法对析取实体进行加权?我希望正则表达式首先找到最高的“加权”标识符。村委会而不是简单的村,例如“catelephant”而不是“cat”。在初步实验中,正则表达式解析器显然从左到右寻找析取匹配。这是一个有效的假设吗?我应该将最常出现的标识符放在分离列表的首位吗?

如果我失去了任何与中国相关的细节,我很抱歉,如果需要可以进一步澄清。这个例子真的不必是中文的——我认为更一般地说,这是一个关于正则表达式分离匹配机制的问题——它优先选择分离实体的顺序,以及它如何决定何时“调用它”一天”在懒惰搜索的背景下?

在某种程度上,在懒惰和贪婪搜索之间是否存在某种中间立场?在最长/最高加权分离实体之前找到你能找到的最小位?懒惰,但如果可以的话,为了彻底而付出一点额外的努力?(顺便问一下,我大学的工作理念?)

4

1 回答 1

8

如何处理交替取决于特定的正则表达式引擎。对于几乎所有引擎(包括 Perl 的正则表达式引擎),交替匹配 - 也就是说,它首先匹配最左边的选择,并且只有在失败时才尝试另一个选择。例如,如果你有/(cat|catelephant)/它永远不会匹配catelephant. 解决方案是重新排序选择,以便最具体的选项排在第一位。

于 2011-01-28T20:12:24.427 回答