我有以下正则表达式,用于查找我需要解析的文件区域:
public static readonly Regex ObjectAction = new Regex($@"(?<Shape>{GetShapeOrRegexSnippet}).+?userdatas"".*?action=(?<ActionType>w+)^(?<ActionPropertyString>.*?)^""", RegexOptions.Singleline);
其中GetShapeOrRegexSnippet
定义如下:
private static string GetShapeOrRegexSnippet => ShapeCodes.Aggregate((i, j) => i + '|' + j);
这匹配了我收藏中遇到ShapeCodes
之一(rect
、circ
、line
等)和以. userdata
开头的行之间的区域(包括)。这适用于格式良好的部分,例如:
line
16.5894 34.4828 34.8993 46.3054 19.6616 41.3793
11.6741 44.9507
. filled 1
. dynprop
(FOX_VAR_3
(= *
(ecolor FOX_VAR_3)))
(o2
(= *
(call fox_oos(__self))))
. userdata "FOX_VAR=3^attr=ECOLOR^attrval=3^required=0^var=UPDATETAG33^delta=1.000000^conv=LOOKUP^type=LONG^minstate=0^num_entries=2^entries=7,7^END_FOXV= ^oos_obj=0002"
但是,给定的形状完全有可能没有关联的userdata
字符串,因此是否可以规定,如果Regex
在遇到userdata
字符串之前再次遇到任何ShapeCodes
,它将不匹配该部分并将继续检查文件的其他部分?
我最初的想法是使用负面的展望,但这不起作用(我对Regex
很陌生,所以我可能做错了什么):
(?<Shape>rect|frect|fpie|spline|poly|line|fsec|fcir).+?(?!rect|frect|fpie|spline|poly|line|fsec|fcir)userdatas".*?attr=(?<AttributeType>w+)^(?<AttributePropertyString>.*?)^(?=(?:END_FOXV))
这可能吗?如果是这样,你能不能指出我正确的方向,如果没有,你能告诉我,我会尝试不同的方法。
关键是.+?
尽可能少地匹配任何 1+ 个字符,但从{GetShapeOrRegexSnippet}
的第一场比赛开始。这就是为什么它可以跨多个块匹配的原因。
将第一个.+?
替换为(?:(?!{GetShapeOrRegexSnippet}|action=).)*
,一个经过回火的贪婪令牌,它将只匹配不启动与{GetShapeOrRegexSnippet}
或action=
匹配的序列的 0+ 字符。
也许我不明白你的问题,但你不能把整个部分(我想是userdata
块)包裹在括号里并在它后面放一个?
吗? 这将匹配该块的零个或一个实例。 像这样的东西(只显示正则表达式的userdata
块):
(?:userdatas"".*?action=(?<ActionType>w+)^(?<ActionPropertyString>.*?)^"")?