修改数字列表和数值范围表达式的正则表达式

时间:2009-11-16 18:11:24

标签: regex extjs

我正在使用ExtJS。使用ExtJS组件制作的文本字段之一应该允许逗号分隔的数字/操作符字符串(3个类似示例),如

1, 2-3, 4..5, <6, <=7, >8, >=9 
>2, 3..5, >=9,>10
<=9, 1, <=8, 4..5, 8-9

这里我使用的是equals,range( - ),sequence(..)&amp;对于小于或等于100的数字,大于/等于运算符。这些数字用逗号分隔。

这种类型的字符串的正则表达式是什么?

对于我之前提出的问题..我从“dlamblin”获得了一个解决方案: ^(?:\d+(?:(?:\.\.|-)\d+)?|[<>]=?\d+)(?:,\s*\d+(?:(?:\.\.|-)\d+)?|[<>]=?\d+)*$

这适用于所有模式,除了:

  1. 仅当关系运算符(<<=>>=)作为字符串的第一个元素存在时。例如。 <=3, 4-5, 6, 7..8工作正常,但<=3, 4-5, 6, 7..8, >=5关系运算符不在字符串的第一个元素。

  2. 同时字符串<3<4, 5, 9-4不会出现任何错误,即虽然<3<4之间需要使用逗号,但条件仍然令人满意。

  3. 字符串中的数字应小于或等于100.即<1000-10099..100

  4. 不应允许前导零(例如003099

4 个答案:

答案 0 :(得分:9)

废弃并使用标记器代替。用逗号分隔字符串,然后查看每个标记并决定(可能使用正则表达式)它是什么类型的关系。如果它不是现有的关系,则它是无效的。如果任何关系包含的数字太大,则无效。

为了您的理智以及在完成此代码后必须维护此代码的人员,请不要使用正则表达式来验证这种复杂的相互关联的规则集。把它分解成更简单的块。

答案 1 :(得分:2)

Welbog's advice使用标记器是理智的选择。

如果您有其他强制正则表达式的约束,则可以使用

^(<|<=|>|>=)?\s*(100|0|[1-9]\d?)((\.\.|-)(100|0|[1-9]\d?))?(,\s*(<|<=|>|>=)?\s*(100|0|[1-9]\d?)((\.\.|-)(100|0|[1-9]\d?))?)*$

这是手动扩展以下内容的结果:

num   = (100|0|[1-9]\d?)
op    = (<|<=|>|>=)
range = op?\s*num((\.\.|-)num)?
expr  = ^range(,\s*range)*$

答案 2 :(得分:1)

这应该有效:

^(?:(?:\s*((?:\<|\>|\<\=|\>\=)?(?:[1-9]|[1-9]\d|100))\s*(?:,|$))|(?:\s*((?:[1-9]|[1-9]\d|100)(?:\.\.|\-)(?:[1-9]|[1-9]\d|100))\s*(?:,|$)))*$

(显然,您需要使用“多行”选项。)

如果您拥有支持“忽略空白”选项的正则表达式引擎的优势,那么您可以将其分解为:

^                           # beginning of line
(?:   
  (?:
    \s*                     # any whitespace
    (                       # capture group
      (?:<|>|<=|>=)?        # inequality
      (?:[1-9]|[1-9]\d|100) # single value
    )
    \s*                     # any whitespace
    (?:,|$)                 # comma or end of line
  )
  |
  (?:
    \s*                     # any whitespace
    (                       # catpure group
      (?:[1-9]|[1-9]\d|100) # single value
      (?:\.\.|\-)           # range modifier
      (?:[1-9]|[1-9]\d|100) # single value
    )
    \s*                     # any whitespace
    (?:,|$)                 # comma or end of line
  )
)+                          # one or more of all this
$                           # end of line

如您所见,它与Expresso中的示例匹配:

http://imgur.com/5ctQS.png

答案 3 :(得分:1)

我同意Welbog的说法,处理前/后应该是更好的选择。

但是因为我喜欢RegEx所以这是我的解决方案。

^[ \t]*(?:(?:0|[1-9][0-9]?|100)(?:(?:\-|\.\.)(?:0|[1-9][0-9]?|100))?|(?:[<>]=?)(?:0|[1-9][0-9]?|100))(?:[ \t]*,[ \t]*(?:(?:0|[1-9][0-9]?|100)(?:(?:\-|\.\.)(?:0|[1-9][0-9]?|100))?|(?:[<>]=?)(?:0|[1-9][0-9]?|100)))*[ \t]*$

'\s'未使用,因为它可能在某些引擎中包含“\n”。

'\d'未被使用,因为您需要[1-9],因此[0-9]将更易于使用。

'(?:0|[1-9][0-9]?|100)'将匹配0到100之间的数字而不会导致零。

'(?:[&lt;&gt;]=?)(?:0|[1-9][0-9]?|100)'会匹配条件后跟一个数字(如果你想匹配'=',只需调整它)。

'(?:0|[1-9][0-9]?|100)(?:(?:\-|\.\.)(?:0|[1-9][0-9]?|100))?'将匹配带有可选范围或序列的数字。

完整解释:

^
[ \t]*  // Prefix spaces
(?: // A valid term
    // A number
    (?:0|[1-9][0-9]?|100)
    // Optional range or sequence
    (?:
        (?:\-|\.\.)
        (?:0|[1-9][0-9]?|100)
    )?
    |
    // Condition and number
    (?:[<>]=?)(?:0|[1-9][0-9]?|100)
)
(?: // Other terms
    [ \t]*,[ \t]*   // Comma with prefix and suffix spaces
    (?: // A valid term
        // A number
        (?:0|[1-9][0-9]?|100)
        // Optional range or sequence
        (?:
            (?:\-|\.\.)
            (?:0|[1-9][0-9]?|100)
        )?
        |
        // Condition and number
        (?:[<>]=?)(?:0|[1-9][0-9]?|100)
    )
)*
[ \t]*  // Tail spaces

我使用Eclipse的正则表达式搜索进行测试,它可以工作。

希望这有帮助。