正则表达式循环解析与否定词前瞻

时间:2014-04-03 16:51:06

标签: regex parsing regex-negation

我正在尝试解析以下字符串,但我似乎无法弄清楚如何对单词使用正则表达式否定。我有以下短信历史记录。

string = '2014-03-29 10:29:24 AM: John Doe: Hey dude how are you feeling 2014-03-29 10:30:39 AM: Billy: Hey Doe, Im feeling better now. 2014-03-29 10:30:58 AM: Billy: Yup'

我的正则表达式ruby查询目前看起来像这样:

string.scan(/((\d{4}-\d{2}-\d{2}\s+\d{2}\:\d{2}\:\d{2}\s+[AP][M])\:\s(.*?)\:\s([^\d{4}]*))/) {|match| puts match}

Output:
   2014-03-29 10:29:24 AM: John Doe: Hey dude how are you feeling 
   2014-03-29 10:29:24 AM
   John Doe
   Hey dude how are you feeling 
   2014-03-29 10:30:39 AM: Billy: Hey Doe, Im feeling better now. 
   2014-03-29 10:30:39 AM
   Hason
   Hey Doe, Im feeling better now. 
   2014-03-29 10:30:58 AM: Billy: Yup
   2014-03-29 10:30:58 AM
   Billy
   Yup

问题

我的正则表达式否定仅适用于字符,而不适用于单词。 [^ \ d {4}] 仅在检测到任何数字时停止,而不是像“2014'”这样的词。

3 个答案:

答案 0 :(得分:1)

尝试以下方法。我使用了?:来避免从你的正则表达式中捕获很少的组。此外,添加了一个积极的预测(?=\d{4}-|$),以查看是否有任何\d\d\d\d-格式在下一行或其末尾可用。如果需要,您可以将其更改为您的模式(我的意思是将其改为yyyy-mm-dd格式)。

string.scan(/((?:\d{4}-\d{2}-\d{2}\s+\d{2}\:\d{2}\:\d{2}\s+[AP][M])\:\s(?:.*?)\:.*?)(?=\d{4}-|$)/) {|match| puts match}

输出:

2014-03-29 10:29:24 AM: John Doe: Hey dude how are you feeling 
2014-03-29 10:30:39 AM: Billy: Hey Doe, Im feeling better now. 
2014-03-29 10:30:58 AM: Billy: Yup

答案 1 :(得分:0)

您可以匹配所有特定的"字"像这样的例子,单词" 2014":

(?>[^2]+|2(?!014))*

与未知年份(四位数)相同:

(?>[^0-9]+|[0-9](?![0-9]{3}-))*

另一种方法是使用前瞻分割字符串:

string.split(/(?=\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}\s+[AP][M]:)/)

注意:对于这三种模式,您可以选择在预测断言中使用子模式的长度和精度来特定的方式。

答案 2 :(得分:0)

角色类不会像这样工作。

[^\d{4}]*

意义:

^    -  Negative class, so -
\d   -  Not digit 0-9
{    -  Not '{'
4    -  Not '4'
}    -  Not '}'

并且,该类可选择多次匹配此组 因此,它会停止,并且不会匹配数字Not digit 0-9

匹配,直到4位数字也可能像这样

 (                             # (1 start)
      (                             # (2 start)
           \d{4} - \d{2} - \d{2} 
           \s+ 
           \d{2} \: \d{2} \: \d{2} 
           \s+ 
           [AP] [M] 
      )                             # (2 end)
      \: \s 
      ( .*? )                       # (3)
      \: \s 
      (                             # (4 start)
           (?:
                (?! \d{4} )              # Not 4 digits ahead of this character
                .                        # Ok, match the character
           )*
      )                             # (4 end)
 )                             # (1 end)