我需要捕获Sereral组,其中一些是可选的。我已经在https://www.regular-expressions.info/optional.html中阅读了有关可选的内容,但?
对我不起作用。示例文件:
Code>1<Code
foo
Prod>2<Prod
foo
Type>3<Type
perl -0777ne 'print qq($1;$2;$3) if /Code>(.*?)<Code.*?Prod>(.*?)<Prod.*?Type>(.*?)<Type/s' < tst.txt
按预期提供1;2;3
。
现在,我想为第二组添加可选性,例如perl -0777ne 'print qq($1;$2;$3) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod)?.*?Type>(.*?)<Type/s' < tst.txt
,但是它停止打印第二组,并给出1;;
(由于嵌套的第3个空白与第2个相同,$ 4打印{{1} }。
每Optional Group Expression我都尝试过3
,但又尝试过perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod|.*?).*?Type>(.*?)<Type/s' < tst.txt
。
是否可以在任意位置进行提取,因为我可以在组之间添加其他内容?
编辑:
删除一个1;;;3
?
会给出
perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(Prod>(.*?)<Prod|.*).*?Type>(.*?)<Type/s' < tst.txt
因此将捕获第一和第三之间的所有内容(看起来像提取了第二个选项,而不是1;
foo
Prod>2<Prod
foo
;;3
之前的一个),而不仅仅是第二个。
编辑:
实施了|
条建议,现在?:
给出了perl -0777ne 'print qq($1;$2;$3;$4) if /Code>(.*?)<Code.*?(?:Prod>(.*?)<Prod|.*).*?Type>(.*?)<Type/s' < tst.txt
答案 0 :(得分:3)
您正在寻找(?:...)
-捕获组中的?:
前缀将其简单地分为一个组,而不是捕获的组。我建议每次都没有捕获一个组时使用它,以使您的意图更清晰。它说:“我将其分组,但不保留。”它甚至可以使运行时更快,但这不是主要优点。
示例:
perl -0777nE 'say qq[$1;$2;$3] if /Code\>(.*?)\<Code.*?(?:Prod\>(.*?)\<Prod.*?)?Type\>(.*?)\<Type/s' < t
这会打印出1;2;3
但是,我还建议您查看(?<name>...)
语法,在其中您可以命名组并使用%+
(例如$+{name}
)按名称而不是位置提取字段。以我的经验,这使得正则表达式和依赖它的代码都更具可读性。