我想在C#中为我的规则创建一个Regex验证。我有以下规则:
@N [货币] [签字]大小[签字] [货币]
([$]|[~][^~]*[~])?
-
[1-9][0-9]*
(仅限尺寸)这是正则表达式:[@][nN]([$]|[~][^~]*[~])?-?[1-9][0-9]*-?([$]|[~][^~]*[~])?
我的问题是货币和标志只能在尺寸的左侧或右侧出现一次。这意味着如果标志已经在尺寸左侧,则不应再出现在右侧,货币也是如此。
使用正则表达式可以做到这一点吗?
以下内容应符合:
以下不匹配:
答案 0 :(得分:2)
我不知道C#是否支持条件表达式,但如果支持,则可以使用:
\@[nN](\$)?(-)?[1-9]\d*(?(2)|-)(?(1)|\$)(?:\s|$)
<强>解释强>
\@[nN] : @ followed by n case insensitive
(\$)? : optional $ sign captured in group 1
(-)? : optional minus sign captured in group 2
[1-9]\d* : value
(?(2)|-) : if group 2 exists then nothing, else minus sign
(?(1)|\$) : if group 1 exists then nothing, else $ sign
(?:\s|$) : a space or end of line
以下是perl脚本示例:
use Modern::Perl;
my $re = qr~\@[nN](\$)?(-)?[1-9]\d*(?(2)|-)(?(1)|\$)(?:\s|$)~;
while(<DATA>) {
chomp;
say (/$re/ ? "OK: $_" : "KO: $_");
}
__DATA__
@N$7-
@N-7$
@N$-7
@N7-$
@N$5$
@N$-5-
@N-5-
@N7$-
@N-$7
<强>输出:强>
OK: @N$7-
OK: @N-7$
OK: @N$-7
OK: @N7-$
KO: @N$5$
KO: @N$-5-
KO: @N-5-
KO: @N7$-
KO: @N-$7
答案 1 :(得分:2)
您可以使用构造^(?!.*pattern.*pattern)
禁止重复模式。对于您的情况,正则表达式如下所示:
(?mx)^
(?!.*([$]|~[^~]*~).*([$]|~[^~]*~))
(?!.*-.*-)
@[nN]([$]|~[^~]*~)?-?[1-9][0-9]*-?([$]|~[^~]*[~])?$
正则表达式演示:https://regex101.com/r/YBhQPB/1
答案 2 :(得分:2)
如果您对使用C#运行其他测试的正则表达式解决方案没问题,可以编写一个简单的方法来验证两个组中只有一个捕获值:
static bool HasOnlyOne(Match m, int g1, int g2) {
if (!m.Success) {
return false;
}
var has1 = m.Groups[g1].Success;
var has2 = m.Groups[g2].Success;
return !has1 || !has2;
}
使用此功能,您可以使用略微修改版本的正则表达式执行以下测试:
var r = new Regex(
@"^[@][nN]([$]|[~][^~]*[~])?(-)?[1-9][0-9]*(-)?([$]|[~][^~]*[~])?$"
// ^ ^ ^ ^
);
string s;
while ((s = Console.ReadLine()) != null) {
var m = r.Match(s);
bool good = HasOnlyOne(m, 1, 4) && HasOnlyOne(m, 2, 3);
if (good) {
Console.WriteLine("Match: {0}", s);
} else {
Console.WriteLine("Fail: {0}", s);
}
}
我在评论中使用^
标记对您的正则表达式进行了修改。