0
"^(?:(2\d\d\d)\s+)?(?:Comm\. Rep\.\s+)?(?:CONG\s+)?(\S+)\s+(\S+)\s+(?:No\.\s+)?(\S+)(?:\s+\(.*?\))?$"

目前这能够解析一个字符串,如

2009 IA H.B. 184 (NS)

我怎样才能让它解析像这样的文本

2009 IA HEART RATE 184 (NS)

我正在寻找一个可以解析间隔单词 HEART RATE 的调整。

编辑:只要第三个单词没有间隔,它似乎就可以工作。例如,它适用于 2009 IA REG 184 (NS) ... 但是一旦第三个单词实际上是由空格组成的,它就会像 HEART RATE 一样失控。

4

2 回答 2

0

我将假设您想要所有这些空格分隔的单词,这现在不起作用,因为您试图HEART RATE通过阅读直到找到空格来阅读“第三个单词”(第二个正则表达式捕获组) (第二个(\S+))。

为了解决这个问题,我假设你“第三个单词”是所有空格分隔的单词,直到你点击一个数字或一个以开头的单词No.(告诉我这个假设是否错误!)。这是((?:\S|\s(?!\d|No\.))+)解决方案中的。

这是我的解决方案:

"^(?:2\d{3}\s+)?(?:Comm\. Rep\.\s+)?(?:CONG\s+)?(\S+)\s+((?:\S|\s(?!\d|No\.))+)\s+(?:No\.\s+)?(\S+)(?:\s+\(.*?\))?$"

当我测试它时

2009 年 IA HB 184 (NS)

它(仍然)发现第三个词是H.B.

当我测试它时

2009 IA 心率 184 (NS)

它发现第三个词是HEART RATE

当我测试它时

2009 IA 心率无 184 (NS)

它发现第三个词是HEART RATE None

当我测试它时

2009 年 IA 心率第 184 号 (NS)

它发现第三个词是HEART RATE

看起来挺好的?

PS gskinner很棒。

于 2012-08-09T23:08:05.103 回答
0

让我们把表达式分解成几个部分:

  1. ^
    从一行的开头开始。

  2. (?:(2\d\d\d)\s+)?
    如果出现年份,则将其捕获在第 1 组中(第 0 组是整个事件)。如果没有给出年份也没关系。

  3. (?:Comm\. Rep\.\s+)?
    接受字符串“Comm. Rep.” 和一个或多个空白字符,但不捕获它。如果它不存在也没关系。

  4. (?:CONG\s+)?
    接受字符串“CONG”和一个或多个空格字符,但不要捕获它。如果它不存在也没关系。

  5. (\S+)\s+(\S+)\s+
    必须有两个至少一个字符长度的非空白字符块,每个字符后跟至少一个空格。捕获第 2 组和第 3 组中的块。

  6. (?:No\.\s+)?
    接受字符串“否”。和一个或多个空白字符,但不捕获它。如果它不存在也没关系。

  7. (\S+)
    必须存在另一个至少有一个非空白字符的块。在第 4 组中捕获它。

  8. (?:\s+\(.*?\))?
    接受至少一个空格,然后是任何内容,只要它在括号内,但不要捕获它。如果它不存在也没关系。

  9. $
    然后该行必须结束。

以下是部分如何映射到当前匹配项(省略行首和行尾):

2009 IA H.B. 184 (NS)
---- ------- --- ----
2    5       7   8

您的问题在于表达式的第 5 部分,因为只接受两个“块”:

2009 IA HEART RATE 184 (NS)
---- ------------- --- ----
2    ???           7   8

假设字符串“HEART RATE”也应该进入第三组,您需要将第 5 部分替换为:

(\S+)\s+
接受至少一个非空白字符块,后跟至少一个空白字符,并将其捕获到第 2 组(未更改)。

(.+?)\s+
接受任何内容的至少一个字符,后跟一个空格,并捕获除第 3 组中的最后一个空格之外的所有字符。

所以,这是你需要的整体表达:

^(?:(2\d\d\d)\s+)?(?:Comm\. Rep\.\s+)?(?:CONG\s+)?(\S+)\s+(.+?)\s+(?:No\.\s+)?(\S+)(?:\s+\(.*?\))?$

顺便说一句,我对http://regexpal.com非常满意。

PS:Carl Walsh 的解决方案在性能方面更聪明,因为它不依赖于非贪婪(或懒惰)捕获。

于 2012-08-09T23:46:04.850 回答