【问题标题】:Regex: optional group正则表达式:可选组
【发布时间】:2009-08-27 11:21:46
【问题描述】:

我想这样分割一个字符串:

abc//def//ghi

进入//第一次出现前后的部分:

a: abc
b: //def//ghi

我目前正在使用这个正则表达式:

(?<a>.*?)(?<b>//.*)

到目前为止效果很好。

但是,有时源字符串中缺少//,显然正则表达式无法匹配。如何将第二组设为可选?

abc 这样的输入应该匹配到:

a: abc
b: (empty)

我尝试了(?&lt;a&gt;.*?)(?&lt;b&gt;//.*)?,但这让我在 Expresso 中有很多 NULL 结果,所以我猜这是错误的想法。

【问题讨论】:

  • 您确定需要正则表达式吗?
  • Regex 做得很好,没有理由不使用它。
  • 正则表达式永远不是needed。在这种情况下,我喜欢使用正则表达式,因为上面只是需要正则表达式的更大的简化部分。

标签: regex


【解决方案1】:

尝试在表达式的开头使用 ^ 以匹配字符串的开头,在结尾尝试使用 $ 以匹配字符串的结尾(这将使非贪婪匹配起作用)。

^(?<a>.*?)(?<b>//.*)?$

【讨论】:

  • 显然是问题中的第二个表达式(在第二组之后带有尾随 ? 的那个)。
  • 我在尝试这个时得到一个 NULL 结果。
  • @mafutrct - 我没有通过 expresso 运行它,所以没有注意到不贪婪的匹配,添加了一个 $ 来修复它。现在可以正常工作了。
  • 太棒了!还要感谢 Kamarey,他刚刚删除了他的正确答案。
  • ^(?&lt;a&gt;.*?)(?://(?&lt;b&gt;.*))?$ 可能会更好。无需捕获//
【解决方案2】:

Stevo3000 答案的证明(Python):

import re

test_strings = ['abc//def//ghi', 'abc//def', 'abc']

regex = re.compile("(?P<a>.*?)(?P<b>//.*)?$")

for ts in test_strings:
    match = regex.match(ts)
    print 'a:', match.group('a'), 'b:', match.group('b')

a: abc b: //def//ghi
a: abc b: //def
a: abc b: None

【讨论】:

    【解决方案3】:

    为什么要使用组匹配?为什么不直接按"//" 拆分,作为正则表达式或纯字符串?

    use strict;
    
    my $str = 'abc//def//ghi';
    my $short = 'abc';
    
    print "The first:\n";
    my @groups = split(/\/\//, $str, 2);
    foreach my $val (@groups) {
    print "$val\n";
    }
    
    print "The second:\n";
    @groups = split(/\/\//, $short, 2);
    foreach my $val (@groups) {
    print "$val\n";
    }
    

    给予

    The first:
    abc
    def//ghi
    The second:
    abc
    

    [编辑:固定返回最多 2 个组]

    【讨论】:

    • 第一个 // 之后的所有 // 都将被忽略。
    • 我没听懂。我仍然认为我的解决方案是最容易理解的,使用大多数拆分函数中存在的限制参数。
    猜你喜欢
    • 2010-11-04
    • 2013-09-09
    • 1970-01-01
    • 2020-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-21
    相关资源
    最近更新 更多