我有一个从配置文件中读取的字符串。字符串的结构如下;
(long_string)long_string(long_string)
括号中的任何项目(包括括号本身)都是可选的。我有以下正则表达式匹配整个字符串,但我无法弄清楚如何使用“?”使正则表达式的某些部分可选。
以下是一些有效的输入字符串
(a)like(1)
like(very long string here)
like
这是我的正则表达式只匹配第一个;
^\((?<short>.*)\)(?<text>.*)\((?<return>.*)\)$
如何将我的正则表达式转换为匹配可选括号?
答案 0 :(得分:5)
使用不匹配的群组(?:
expr
)
围绕这两个子模式并将其设为可选:
^(?:\((?<short>.*)\))?(?<text>.*)(?:\((?<return>.*)\))?$
如果可能的话,使通用表达式.*
更具体,可能使用[^()]+
:
^(?:\((?<short>[^()]+)\))?(?<text>[^()]+)(?:\((?<return>[^()]+)\))?$
答案 1 :(得分:4)
使用下面的代码,您将始终获得一个由三个元素组成的@matches数组。如果其中一个可选部件不匹配,则相应的条目将为undef。
#!/usr/bin/perl
use strict;
use warnings;
my $optional = qr/(?:\(([^)]+?)\))?/;
my $required = qr/([^()]+)/;
while ( my $line = <DATA> ) {
chomp $line;
last unless $line =~ /\S/;
if ( my @matches = ($line =~ /$optional$required$optional/) ) {
no warnings 'uninitialized';
print "---$_---\n" for @matches;
}
}
__DATA__
(a)like(1)
like(very long string here)
like
答案 2 :(得分:1)
我要做的是用你的分组成员包装(和),而不是
\((?<short>.*)\)
将其更改为:
(\(<short>.*\))
这样它会匹配()和内部文本。然后,如果它们存在则使用另一个正则表达式来消除括号。
我对命名匹配语法不是很熟悉,所以组语法可能会关闭,但您应该明白这一点。
答案 3 :(得分:0)
试一试......
string[] strings = new string[] { "(a)like(1)", "like(very long string here)", "like" };
foreach (string s in strings)
{
System.Text.RegularExpressions.Match match = System.Text.RegularExpressions.Regex.Match(s, @"^(\((?<short>.)\))?(?<text>.+)?(\((?<return>.+)\))?$");
if (match.Success)
{
// do logic to handle the match
}
}
答案 4 :(得分:0)
好吧,只需将它们作为可选项,然后:
^(?<short>\(.*\))?(?<text>.*)(?<return>\(.*\))?$
我不喜欢命名的捕获,它们往往使它看起来比它复杂(至少对我而言)。另外,我建议不要使用“.*
”。我的建议是:
^(\([^)]*\))?([^(]*)(\([^)]*\))?$
然后去匹配组2.但是如果你坚持使用命名捕获:
^(?<short>\([^)]*\))?(?<text>[^(]*)(?<return>\([^)]*\))?$