【问题标题】:Regex to identify numbers except when enclosed by "[" "]"正则表达式识别数字,除非用“[”“]”括起来
【发布时间】:2013-11-08 17:35:05
【问题描述】:

我想写一个正则表达式,这样我只匹配第一个不被方括号括起来的数字。

例如asdadsas,*&(*&(*2asdasd*U(*&*()&(*3 应该匹配 2(没有方括号)

asdadsas,*&(*&(*[2]asdasd*U(*&*()&(*3 应该匹配 3

我目前的正则表达式是:(?<!\[)[0-9](?!\])

但是,我遇到的问题是 [2 仍应匹配 2。

我只想跳过左边有[ 和右边有] 的号码。

我不知道如何(或者是否可能)在正则表达式中实现这种条件逻辑。

【问题讨论】:

  • 澄清:数字是方括号中唯一的东西吗?如果字符串开头附近有[2a],应该跳过还是返回?
  • 嗯。你知道我没有想到什么......我认为就这个问题而言,这并不重要。但如果你能同时展示两种方式会很酷:p 即如果它只适用于 [2] 我会给你打勾:)
  • 你需要指定你正在使用的语言。java不支持lookbehind中的量词,javascript根本不支持lookbehind
  • +1 我们这里有一个很好的正则表达式问题:目标通过示例很好地说明,OP 已经做出了合理的尝试(这在大多数情况下都有效),并且显示了问题(再次举例)并清楚地解释。
  • @iamnotmaynard 唯一缺少的是缺少哪个正则表达式引擎,但仍然值得 +1

标签: regex


【解决方案1】:

以下应该有效:

[0-9](?!(?<=\[.)\])

示例:http://rubular.com/r/0vKy8hyMy0

解释:[0-9] 匹配一个数字,(?!(?&lt;=\[.)\]) 强制要求该数字前后的字符分别不是[]。要打破这一点,请考虑以下正则表达式:

(?<=\[.)\]

这可以读作“匹配一个],但前提是两个地方之前的字符是[”。通过在我们匹配数字后将其放入负前瞻中,如果前两个位置的字符是 [ 而下一个字符是 ],我们可能会失败。

【讨论】:

  • 如果需要任意位数,[0-9]+(?!(?&lt;=\[[0-9]+)\]) 可以吗?
  • 只有在支持可变长度后视的情况下,您才能使用反向引用:([0-9]+)(?!(?&lt;=\[\1)\])
  • @F.J:最后一个模式(多位数字)不能工作有两个原因。第一个是正则表达式引擎将在最后一个数字之前回溯(例如:[123] 将给出12 作为结果)。第二个仅适用于不支持可变长度后视的引擎:使用反向引用不会使后视内的子模式变少。
  • 您可以使用交替解决这些问题:(?&lt;=\[)\d++(?!])|(?&lt;![\[\d])\d+(?&lt;=\[)\d+(?!\d|])|(?&lt;!\[|\d)\d+,或使用条件 (PCRE):(?(?&lt;=\[)\d++(?!])|(?&lt;!\d)\d+)
【解决方案2】:
(?!    # start negative lookahead
    \[ # open bracket
    \d # digit (use \d+ if needed)
    \] # close bracket
)      # end negative lookahead
\[     # literal bracket
(\d)   # capture digit
|      # alternation (OR)
(?<!   # start negative lookbehind
\[     # literal bracket
)
(\d)   # capture digit

这将捕获数字作为反向引用。如果您需要数字完全匹配,您可以使用前瞻。

http://rubular.com/r/C8YSRiY1d0

【讨论】:

    【解决方案3】:

    我相信最适合您的正则表达式是:

    (?<!\[)[0-9]+|[0-9]+(?!\])
    

    现场演示:http://www.rubular.com/r/xWXFg7QXZJ

    【讨论】:

      【解决方案4】:

      尝试使用环视和交替。这匹配前面没有[ 的数字或后面没有] 的数字:

      (?<!\[)\d|\d(?!\])
      

      为了让它处理多于一位的数字,您需要添加环视以确保前一个/下一个字符既不是括号也不是数字:

      (?<!\[|\d)\d+|\d+(?!\]|\d)
      

      即。 (使用 Ruby;应该在其他地方类似地工作):

      >> rex = /(?<!\[|\d)\d+|\d+(?!\]|\d)/
      >> "&(*25asdasd*U(*&*()&(*3".match rex #=> #<MatchData "25">
      >> "&(*[25asdasd*U(*&*()&(*3".match rex #=> #<MatchData "25">
      >> "&(*25]asdasd*U(*&*()&(*3".match rex #=> #<MatchData "25">
      

      但是

      >> "&(*[25]asdasd*U(*&*()&(*3".match rex #=> #<MatchData "3">
      

      【讨论】:

        【解决方案5】:

        仅正则表达式的解决方案将是一种矫枉过正

        只需使用(^|\D)(\d+)($|\D),然后选择符合您条件的第一个..

        在c#中,你可以这样做

        string output=Regex.Matches(input,@"(^|\D)(\d+)(\D|$)")
                           .Cast<Match>()
                           .Where(x=>!(x.Value.StartsWith("[")&& x.Value.EndsWith("]")))
                           .First()
                           .Groups[2]
                           .Value;
        

        【讨论】:

          猜你喜欢
          • 2018-09-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-05-11
          • 1970-01-01
          • 1970-01-01
          • 2011-11-20
          • 1970-01-01
          相关资源
          最近更新 更多