假设我有两个这样的字符串:
XABY
XBAY
与两者匹配的简单正则表达式将如下所示:
X(AB|BA)Y
但是,我有一个案例,其中A和B是复杂的字符串,我正在寻找一种方法来避免必须两次指定它们(在|的每一侧)。有没有办法做到这一点(可能比指定它们两次更简单)?
由于
答案 0 :(得分:21)
X(?:A()|B()){2}\1\2Y
基本上,你使用一个空的捕获组来检查每个项目是否匹配,然后反向引用确保所有项目都已被检查。
请注意,这依赖于未记录的正则表达式行为,所以不能保证它会在您的正则表达式中起作用 - 如果确实如此,则无法保证它将继续以此方式工作味道进化。但据我所知,它适用于支持反向引用的每种风格。 (编辑:它在JavaScript中不起作用。)
编辑:您说您正在使用命名组来捕获匹配的部分内容,这会给正则表达式带来很多视觉混乱,即使不是真正的复杂性。好吧,如果你碰巧使用.NET正则表达式,你仍然可以使用简单的编号组作为“复选框”。这是一个简单的例子,可以在不知道内部顺序的情况下查找和挑选一堆月日字符串:
Regex r = new Regex(
@"(?:
(?<MONTH>Jan|Feb|Mar|Apr|May|Jun|Jul|Sep|Oct|Nov|Dec)()
|
(?<DAY>\d+)()
){2}
\1\2",
RegexOptions.IgnorePatternWhitespace);
string input = @"30Jan Feb12 Mar23 4Apr May09 11Jun";
foreach (Match m in r.Matches(input))
{
Console.WriteLine("{0} {1}", m.Groups["MONTH"], m.Groups["DAY"]);
}
这是有效的,因为在.NET中,命名组的存在对非命名组的排序没有影响。命名组具有分配给它们的编号,但这些编号在最后一个非命名组之后开始。 (我知道这看起来很复杂,但有充分的理由这样做。)
通常你想避免一起使用命名和非命名的捕获组,特别是如果你正在使用反向引用,但我认为这种情况可能是合法的例外。
答案 1 :(得分:5)
您可以将regex片段存储在变量中,并执行:
A=/* relevant regex pattern */
B=/* other regex pattern */
regex = X($A$B|$B$A)Y
这样,您只需在自己的行上指定一次正则表达式,这样可以更容易维护。
旁注:你正试图找到排列,这是好的,因为你只看了2个子目标。但是如果你想增加第三个(或第四个),你的正则表达式排列会急剧增长 - (abc | acb | bac | bca | cab | cba) - 或者更糟。如果你需要走上排列的道路,那么stackoverflow就可以对此进行一些很好的讨论。它用于字母排列,解决方案使用awk / bash / perl,但这至少为你提供了一个起点。
答案 2 :(得分:1)
试试这个
X((A|B){2})Y
答案 3 :(得分:0)
如果有多个字符串,其中包含任何类型的字符,那么您最好使用:
X(.)+Y
只有数字
X([0-9])+Y
只有字母
X([a-zA-Z])+Y
字母和数字
X([a-zA-Z][0-9])+Y