高级正则表达式-捕获整个组的复杂语句在替换
本文关键字:复杂 语句 替换 正则表达式 高级 | 更新日期: 2023-09-27 18:07:23
我正在做一个项目,我需要解析相关数据…我使用的工具是完全基于命令的,并返回所有类型的东西,所以regex很方便,而不是猜测这一行是那一行,另一行是这一行,…所以我需要像这样解析它:
1 QB 1283/YR VC MC MO22AUG IFNTHR 2240 2335 100 0 S
根据条件可能会出现在许多形状上,但是,这是有希望的:
.*((/)?(?<Class>('w{2}'s+)+)('w{2}'d{2}'w{3})?'s+'w{6}).*
有一个问题,我只需要捕获这一部分:YR VC MC
,不能保证总有三个。我尝试了括号分组,以及你可以看到的命名,我不知道如何在c#中捕获一个组,虽然我认为它使用Regex->替换,然后用所选组替换整个数据(在听到'Class'组),但它只匹配最后一部分,…内括号,而不是全部。例如,在上面的行中,它将返回"MC"而不是其中的三个,我也试图用('w{2}'s+|'w{2}'s+'w{2}'s+|'w{2}'s+'w{2}'s+'w{2}'s+)
替换('w{2}'s+)+)
,但它也不起作用。
Capture Groups
让我们后退一点。首先,我们需要了解什么是捕获组。括号内的所有内容都将是捕获组。因此,例如,字符串89
的正则表达式('d)('d)
将捕获第一组中的8
和第二组中的9
。假设第二个数字是可选的,所以是('d)('d?)
。现在,如果您尝试匹配8
,那么第一组将是8
,而第二组将只是一个空字符串。通过这种方式,我们可以匹配所有组,即使有些组"缺失"。
Non-Capture组
你的正则表达式似乎有大量不必要的捕获组。如果你不需要,就不要用括号。例如,对于(/)?
,您可以简单地删除括号。如果你想匹配字符串"123"十倍?你可能会做类似(123){10}
的东西。但是,嘿,这是另一个不必要的捕获组!可以使用(?:)
代替()
创建非捕获组。这样,您将不会捕获括号内的任何内容,但您将有效地使用括号来方便。
你Regex
从正则表达式中删除所有不必要的捕获组,我们最终得到:
.*/?('w{2}'s+)+(?:'w{2}'d{2}'w{3})?'s+'w{6}.*.
它包含了捕获组内的空间,所以让我们把它拿出来:
.*/?('w{2})'s+(?:'w{2}'d{2}'w{3})?'s+'w{6}.*.
此时,捕获组('w{2})
只匹配示例字符串中的MC
,因此让我们按照您的做法将其分成三个不同的捕获组。注意,我们不能执行类似('w{2}){1,3}
的操作(它将匹配'w{2}
一到三次),因为它仍然只有一组括号,所以它只有一个捕获组。因此,我们需要将('w{2})'s+
扩展到('w{2})'s+('w{2})'s+('w{2})'s+
。这个正则表达式将正确捕获您的三个字符串。
c#中的正则表达式
在c#中,我们在system . text . regulareexpressions中有这个方便的正则表达式类。你可以这样使用它:string regex = @".*/?('w{2})'s+('w{2})'s+('w{2})'s+(?:'w{2}'d{2}'w{3})?'s+'w{6}.*";
string sample = "1 QB 1283 /YR VC MC MO22AUG IFNTHR 2240 2335 100 0 S";
Match matches = Regex.Match (sample, regex);
string[] stringGroups = matches.Groups
.Cast<Group> ()
.Select (el => el.Value)
.ToArray ();
这里,stringGroups将是包含所有捕获组的字符串数组。stringGroups[0]将是整个匹配(在本例中是1 QB 1283 /YR VC MC MO22AUG IFNTHR 2240 2335 100 0 S
), stringGroups[1]将是第一个捕获组(在本例中是YR
), stringGroups[2]是第二个,stringGroups[3]是第三个。
PS:我强烈推荐Debuggex来测试这类东西
设置为不贪:
.*?((/)?(?<Class>('w{2}'s+)+)('w{2}'d{2}'w{3})?'s+'w{6}).*
^
或者从两端移除两个贪心点。你不需要它们:
/?(?<Class>(?:'w{2}'s+)+)(?:'w{2}'d{2}'w{3})?'s+'w{6}