在Perl中使用正则表达式匹配的问题

时间:2013-03-14 17:23:24

标签: regex perl

我无法在Perl中匹配正则表达式,并且想知道是否有人有任何见解:

这是我的正则表达式:/^-MEMBER:\s+(\b[^,]+)(?:,\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/

这是我匹配的内容:

  

-MEMBER:Doe,John H ID#:3907

正则表达式工作得很漂亮并与上面的行匹配,但是对于任何可能不包含Firstname和Middle的行都有麻烦。示例如下:

  

-MEMBER:Doe,身份证号码:3907

我遇到了与当前正则表达式匹配的问题。

感谢您的帮助!

3 个答案:

答案 0 :(得分:1)

您已将逗号匹配放在可选的名字组中,因此您只能在存在名字的情况下匹配逗号。如果逗号将伴随没有名字的姓氏,则需要将其移至姓氏组。

/^-MEMBER:\s+(\b[^,]+,)(?:\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/

答案 1 :(得分:0)

这个正则表达式将匹配两行:

/
    ^-MEMBER:\s+         # the beginning of the line with "-MEMBER: "
    .*?                  # non greedy
    \s+ID#:\s+(\d+)$     # space and end ID part
/x

答案 2 :(得分:0)

问题在于你真正的语法描述了你的输入。试图一次性描述它变得非常复杂,非常快。有关替代方案,请参阅perl yapp module

但是,如果你坚持只使用正则表达式,我们就去:

/^-MEMBER: # start of line, match specific string
\s+ # must be followed by at least one whitespace char
(\b[^,]+) # now we need to match a word in a capture group
(?:,\s(\b.{1,50}\b)\.?)? # here's the pain, so lets deal with it below
\s+ # more whitespace
ID#: # match this string
\s+ # and some more whitespace
(\d+)$/ # digits at the end of the line

(
 ?: # cluster the following
 ,\s # comma, then a single space
 (
  \b.{1,50}\b # up to fifty "things" bounded by words
 ) # another capture group
 \.? # optional period
)? # zero or one of these I.E. optional capture

这很脆弱,因为它很难将假设编码到你的“语言”中。请注意,如果我们没有第一个/中间名,我们不允许使用逗号,因为它是 inside 可选组。这是你的第二次测试不匹配的问题。

其次,如果我们有第一个/中间名称部分,它可以包含除换行符之外的任何内容。这可能不是您想要或期望的。

解析器有用的原因并不一定是因为它们允许你拥有“上下文”,尽管他们这样做。这是因为它将复杂的正则表达式分解为小的,可管理的部分,这些部分连接在一起成为一个明确定义的整体。通过学习这样的工具,您在这里遇到的问题类型变得微不足道,并且更改

请注意您的正则表达式如何尝试定义每个部分中的“有效”内容。姓氏(\b[^,]+)除逗号外还可以包含任何内容!这是你想要的吗?如果有效名称中只有[a-zA-Z_],会发生什么? ;injectionattemptFTW!!;#是有效名称吗?设计您的程序,以便有一组有限的,明显的条件。对于简单If a then valid, else fail s,a很容易推理。

除非您定义所有可能的特殊情况,否则您将遇到使此正则表达式中断的事情。我无法定义完美的正则表达式,因此您有两种选择:

  1. 在发现特殊情况时,将正则表达式更加复杂
  2. 重新设计以避免需要复杂的正则表达式
  3. 如果您选择第一选项,则此正则表达式可以修复您当前的问题:

    /^-MEMBER:\s+(\b[^,]+),?(?:\s(\b.{1,50}\b)\.?)?\s+ID#:\s+(\d+)$/