JavaScript RegExp语法问题

时间:2011-08-31 12:13:05

标签: javascript regex

我会尽力更好地解释自己; - )。

我正在使用RegexBuddy尝试找到解决方案。 目标是Konfabulator小部件中的JavaScript。

我需要解析的字符串是:

+++++++++++++++++++++ RUNWAY ++++++++++++++++++++++++++++++
1A1093/11  VALID: 1107140300 - 1108301500
  DAILY 0300-1500
  WIP 90M S OF RWY 08/26 AT E, W1, W2.
    NO RESTRICTION DRG TKOF/LDG OR TAX.
1A994/11  VALID: 1106201300 - 1112312059
  PAPI RWY 08 NOT OPR WHEN ILS APCH IN USE. OPR WHEN VIS APCH IN
  USE.
1A987/11  VALID: 1106190615 - UFN
  ILS DME RWY 08 BC 110.90MHZ CH46X OPR.
+++

最终结果应该是以下3个子字符串:

子串1)

1A1093/11  VALID: 1107140300 - 1108301500
  DAILY 0300-1500
  WIP 90M S OF RWY 08/26 AT E, W1, W2.
    NO RESTRICTION DRG TKOF/LDG OR TAX.

子串2)

1A994/11  VALID: 1106201300 - 1112312059
  PAPI RWY 08 NOT OPR WHEN ILS APCH IN USE. OPR WHEN VIS APCH IN
  USE.

子串3)

1A987/11  VALID: 1106190615 - UFN
  ILS DME RWY 08 BC 110.90MHZ CH46X OPR.

正如您所看到的,每个部分都以类似于“1A987 / 11 VALID:”的内容开头,我发现使用此正则表达式:

[0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:

每个部分以下一部分的“1A987 / 11 VALID:”或使用此正则表达式找到的“+++”结束:

([0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:)|(\+{3})

中间的字符是[\ s \ S] +? “。”由于某种原因不起作用。

所以完整的正则表达式是:

[0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:[\s\S]+?(([0-9A-Z]{3,6}/\d{2}\\s{1,3}VALID:)|(\+{3}))

现在由于子串1的结尾是子串2的开头,RegexBuddy找不到子串2,只找到子串1和3。

我正在寻找一种方法来查找所有3个子字符串,因此找到每个子字符串的结尾但是从字符串本身中排除它。

4 个答案:

答案 0 :(得分:1)

我阅读你的问题的方式,重要的事实是:

  1. 每场比赛包括两条或更多条线;
  2. 第一行的开头与您提供的模式匹配;和
  3. 每个后续行都以空格开头。
  4. 以下是我将其表达为正则表达式的方法:

    /^[A-Z0-9]{3,6}/[0-9]{2}[ \t]+VALID:.*(\r?\n[ \t]+.*)+/mg
    

    请注意我在[ \t]+之前和后续行开头使用\s+代替VALID:的方式,仅匹配水平空格字符(空格和/或标签)。然后我使用\r?\n匹配行分隔符(DOS样式\r\n或Unix样式\n)。这样,我永远不会比我需要的更多,使正则表达式更高效,更容易编写和调试。

    最后的m会启用multiline模式,这样^锚点就可以在一行的开头匹配。 g启用global模式,可让您查找所有匹配项,而不仅仅是第一项匹配项。

    顺便说一句,您必须使用[\s\S]而不是.的原因是因为JavaScript没有“单行”或“DOTALL”模式,正如大多数其他正则表达式一样。无法使.匹配为回车(\r)或换行(\n)。但是,如果你明确地匹配行分隔符,那就是你不必处理的另一件事,就像我做的那样。

答案 1 :(得分:0)

我不是百分之百确定你的第二个VALID:在那里做什么,但我认为正则表达式的第二部分是在“|”之后(或者)你看起来像是在尝试捕捉“UFN”的情况,似乎缺少捕获UFN的东西。我不知道该序列的全部可能性,或者您正在使用的正则表达式的实现,但如果您使用[AZ]捕获大写字母,则需要最后一组([AZ] {3 }),或在斜线后面使用通用的字母数字符号而不是加号。

答案 2 :(得分:0)

这取决于我们在这里谈论的语言,但以下正则表达式在Perl中为我工作,s扩展名将行尾作为普通字符处理。

([0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:.+?)([0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:.+?)([0-9A-Z]{3,6}/\d{2}\s{1,3}VALID:.+?)(\+{3})

如果你试图找到一些VALID部分,那么你必须做一个取决于语言的循环。

请注意,我已将[0-9]|[A-Z]折叠为[0-9A-Z],并基本上复制了第一个(...)模式3次。

答案 3 :(得分:0)

我不完全确定你正在使用什么正则表达式解析器,但是给这个野兽一个机会:

((?:(?:[0-9]|[A-Z]){3,6}/\d{2}\s{1,3}VALID:.+?)(?=(?: \+\+\+$|(?:[0-9]|[A-Z]){3,6}/\d{2})))

它使用正向前瞻,因此它可能适用于您,也可能不适合您。

编辑:这是JavaScript中的多行测试:

var match, regex = /([0-9A-Z]{3,6}\/\d{2}\s{1,3}VALID:[\s\S]+?)(?=(?: \+{3}$|(?:[0-9A-Z]{3,6}\/\d{2})))/g;
var s='+++++++++++++++++++++ RUNWAY ++++++++++++++++++++++++++++++\n\
1A1093/11  VALID: 1107140300 - 1108301500 \n\
  DAILY 0300-1500 \n\
  WIP 90M S OF RWY 08/26 AT E, W1, W2. \n\
    NO RESTRICTION DRG TKOF/LDG OR TAX. \n\
1A994/11  VALID: 1106201300 - 1112312059 \n\
  PAPI RWY 08 NOT OPR WHEN ILS APCH IN USE. OPR WHEN VIS APCH IN \n\
  USE. \n\
1A987/11  VALID: 1106190615 - UFN\n\
  ILS DME RWY 08 BC 110.90MHZ CH46X OPR. +++';

while (match=regex.exec(s)){
    alert(match[0]);
}