我试图在.NET中编写一个与客户/事项编号匹配的正则表达式。客户编号或事项编号由一系列字母或数字组成,客户/事项编号是客户编号和由/
,-
或{{分隔的事项编号的组合1}}。例如.
。
在以下字符串中:
Foo [1234/101] bar 456B / 102 baz
我希望它在0204A/101
和[1234-101]
上匹配。我已经提出了这种模式:
456B/102
我可以使用捕获组从每次匹配中提取客户/物品编号。
问题在于:我想排除日期,以便日期的前两个组成部分或最后两个组成部分不会被误解为客户/事项编号匹配。例如,如果我的字符串中有[^a-zA-Z0-9]*([a-zA-Z0-9]+[/\.\-]{1}[a-zA-Z0-9]+)[^a-zA-Z0-9]*
- " Foo [1234-101] bar 456B / 102 baz 5/3/2016",我不想{{1成为一个匹配。为了解决这个问题,我首先尝试将5/3/2016
添加到最终否定范围的末尾:
5/3/
这不起作用,因为我的量词/\.\-
为零或更多,所以它只是将否定范围视为零次并且在[^a-zA-Z0-9]*([a-zA-Z0-9]+[/\.\-]{1}[a-zA-Z0-9]+)[^a-zA-Z0-9/\.\-]*
上匹配。接下来,我尝试制作它,使得否定范围要么出现一次或多次,要么遇到字符串的结尾:
*
然而,这恰好匹配5/3
,这是有道理的。
如何调整模式以匹配一个实例但在重叠实例上失败?例如,我希望它与[^a-zA-Z0-9]*([a-zA-Z0-9]+[/\.\-]{1}[a-zA-Z0-9]+)([^a-zA-Z0-9/\.\-]+|$)
中的/3/2016
和5/3
中的foo 5/3 bar
以及3/2016
中的foo 3/2016 bar
或5/3/
相匹配
答案 0 :(得分:2)
(?<![\/\-\.a-zA-Z0-9])([a-zA-Z0-9]+[\/\-\.][a-zA-Z0-9]+)(?![\/\-\.a-zA-Z0-9])
按照您的要求完美运作,请参阅Regex101 demo
示例:Foo [
1234-101
]栏456B/102
baz 5/3/2016
匹配: 1234-101
和 456B/102
示例:Foo [
1234-101
] bar 5/22/2016
匹配: 1234-101
答案 1 :(得分:0)
使用以下正则表达式:
[^\/0-9a-zA-Z]([0-9a-zA-Z]+[\/.-][0-9a-zA-Z]+)[^\/0-9a-zA-Z]
regexstorm's C# regex tester上的在线演示。
<强> 解释 强>
字符类([...]
)代表单个字符,因此量词{1}
是多余的。
您无需将完整的测试字符串与正则表达式匹配。如果您想这样做,请使用锚点(^
,$
)作为分隔符。按照目前的情况,当指定全局匹配时,正则表达式引擎将匹配所有出现的模式。
前导斜杠和尾随斜杠导致模式不匹配,从而保留日期字符串。
<强> 更新 强>
C#regexen似乎不支持命名字符类,因此从速记中恢复。
添加锚点作为目标模式的替代分隔符。因此,测试字符串开头或结尾的匹配将成功。
答案 2 :(得分:0)
An alternative以环视方式是wrong|(right)
形式的消费模式,因此:
\d+\/\d+\/\d+|(\b\w+[-\/\.]\w+\b)
你匹配并吃掉(并忘记)你不想要的东西,\d+\/\d+\/\d+
,然后在|
之后的第二部分,匹配并记住你想要的东西,{{1 }}