【问题标题】:RegEx a RegEx matchRegEx 一个正则表达式匹配
【发布时间】:2010-09-14 13:01:06
【问题描述】:

我无法为我的字符串构建正确的正则表达式。我想要做的是从我的字符串中获取所有实体;它们以' 开头和结尾。这些实体可以通过一定数量的数字和前面的# 来识别。但是,根本不应该匹配不以 ' 开头或结尾的实体(在本例中为以 # 开头的电话号码)。

我希望有人可以帮助我,或者至少告诉我,我想做的事情在一个正则表达式中是不可能的。谢谢:)

字符串:

'Blaa lablalbl balbla balb lbal '#39'blaaaaaaaa'#39' ('#39#226#8218#172#39') blaaaaaaaa #7478347878347834 blaaaa blaaaa'

正则表达式:

'[#[0-9]+]*'

想要的匹配:

  • '#39'
  • '#39'
  • '#39'
  • '#226'
  • '#8218'
  • '#172'
  • '#39'

找到匹配项:

  • '#39'
  • '#39'
  • '#39#226#8218#172#39' 需要拆分(如果可能在同一个 RegEx 中)

另一个正则表达式:

#[0-9]+

找到匹配项:

  • '#39'
  • '#39'
  • '#39'
  • '#226'
  • '#8218'
  • '#172'
  • '#39'
  • '#7478347878347834' 不应该在这里 :(

语言: C# .NET (4.0)

【问题讨论】:

  • @ApoY2k 因为它不是直接' 字符包围,我猜。不过,可能(可能?)错了。
  • #7478347878347834 是不允许的,因为它是字符串的一部分,因此不是实体。

标签: .net regex c#-4.0


【解决方案1】:

你不能在一个正则表达式中做到这一点,你需要两个:

首先取单引号之间的所有匹配项:

'[\d#]+'

然后在所有这些匹配中,执行以下操作:

#\d+

所以你最终会得到类似(在 C# 中)的东西:

foreach(var m in Regex.Matches(inputString, @"'[\d#]+'"))
{
    foreach(var m2 in Regex.Matches(m.Value, @"#\d+"))
    {
          yield return m2.Value;
    }
}

【讨论】:

  • 太糟糕了,这在一个正则表达式中是不可能的,猜猜这是必须的。谢谢你也帮我打出来;)
  • Gnarf 在一个正则表达式中发布了一个答案,不过谢谢!
【解决方案2】:

假设您可以使用lookbehind/lookaheads,并且您的正则表达式支持可变长度lookbehinds(仅限JGSoft / .NET)

(?<='[#0-9]*)#\d+(?=[#0-9]*')

应该可以...测试了using this site 并得到了这些结果:

   1. #39
   2. #39
   3. #39
   4. #226
   5. #8218
   6. #172
   7. #39

分解很简单:

(?<=        # Start positive lookbehind group - assure that the text before the cursor
            # matches the following pattern: 
  '         # Match the literal '
  [#0-9]*   # Matches #, 0-9, zero or more times
)           # End lookbehind...
#\d+        # Match literal #, followed by one or more digits
(?=         # Start lookahead -- Ensures text after cursor matches (without advancing)
  [#0-9]*   # Allow #, 0-9, zero or more times
  '         # Match a literal '
)

所以,如果前面的文本是 '[#0-9]* 并且后面的文本是 [#0-9]*',则此模式将匹配 #\d+

【讨论】:

  • 哇,完美!正是我想要的。你能解释一下这到底是做什么的吗?非常感谢:)
  • @Willy - 老实说 - 我投票支持@Jan 的回答.. 更容易理解你在做什么......
  • 您说得对,先生。它更容易理解,但如果可能的话,我想在一个正则表达式中做到这一点,这就是你的方法所做的:)。哪种方法会更快、性能更好?
  • @Willy - 很难说哪种方法性能更好(尤其是因为我没有 .NET 编译器),您应该设置某种分析测试以查看...
【解决方案3】:

由于您没有指定语言,这里是 perl 中的解决方案:

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

my $s = qq!Blaa lablalbl balbla balb lbal '#39'blaaaaaaaa'#39' ('#39#226#8218#172#39') blaaaaaaaa #7478347878347834 blaaaa blaaaa!;

my @n = $s =~ /(?<=['#\d])(#\d+)(?=[#'\d])/g;

print Dumper(\@n);

输出:

$VAR1 = [
          '#39',
          '#39',
          '#39',
          '#226',
          '#8218',
          '#172',
          '#39'
        ];

【讨论】:

  • 我不知道 RegEx 是特定于语言的,RegEx 位可以通用,对吗?这也有诀窍,#\d+(?=#|')。谢谢!你的 RegEx 比 Gnarf 发布的要短很多,有什么区别?
  • 他只测试匹配后的字符是#'——并不是所有的正则表达式都可以处理前瞻、后瞻等。如果你在@ 后面加上# 987654326@ 在您的测试字符串中,然后它也会匹配...
  • @gnarf:是的,你说得对,我已经更新了正则表达式,添加了一个固定长度的lookbehind,因为perl 和其他一些语言中不允许可变长度的lookaround。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-04-06
  • 2017-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多