如何使用正则表达式不与包含多行模式中间特定文本的文本匹配
本文关键字:文本 中间 模式 正则表达式 何使用 包含多 | 更新日期: 2023-09-27 18:32:20
我正在尝试创建一个 C# 正则表达式,用于检测我们的 .csproj 文件中的引用何时没有<将 SpecificVersion=">设置为 False(必须在所有
1. <Reference Include="IQ.MyStuff1, Version=4.1.0.0, Culture=neutral, processorArchitecture=MSIL" />
2. <Reference Include="IQ.MyStuff2, Version=4.7.22.21777, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..'..'DebugDLLFiles'IQ.MyStuff2.dll</HintPath>
</Reference>
3. <Reference Include="IQ.MyStuff3, Version=4.1.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..'..'DebugDLLFiles'IQ.MyStuff3.dll</HintPath>
<SpecificVersion>True</SpecificVersion>
</Reference>
4. <Reference Include="IQ.MyStuff4, Version=4.5.3.17401, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>True</SpecificVersion>
</Reference>
所以基本上任何没有明确包含"
因此,让我们忽略第一种情况,因为它不像其他 3 种情况那样具有身体,可以区别对待。 所以这是我到目前为止所拥有的:
<Reference('s|'n|'r)*? # Match against '<Reference '.
Include=""IQ'..*?"" # Match against the entire Include attribute; We only care about IQ DLLs.
('s|'n'r)*?> # Eat any whitespace and match against the closing tag character.
[What should go here?]
</Reference> # Match against the closing tag.
所以我在[这里应该做什么?]块中尝试了很多东西,但似乎无法让任何东西都很好地工作。 我最接近的是在此块中使用以下内容:
(?! # Do a negative look-ahead to NOT match against this Reference tag if it already has <SpecificVersion>False</SpecificVersion>.
(.|'n|'r)*? # Eat everything before the <SpecificVersion> tag, if it even exists.
<SpecificVersion>('s|'n|'r)*?False('s|'n|'r)*?</SpecificVersion> # Specify that we don't want to match if this tag already has <SpecificVersion>False</SpecificVersion>.
)
(.|'n|'r)*? # Eat everything after the <SpecificVersion> tag, if it even existed.
这适用于所有情况,除了在我想要匹配的任何引用下方有一个有效的引用,其中有效的引用如下所示:
<Reference Include='"IQ.MyStuff5, Version=4.5.3.17401, Culture=neutral, processorArchitecture=MSIL'">
<SpecificVersion>False</SpecificVersion>
</Reference>
似乎我正在使用的前瞻性并没有停留在 标签上,而是继续向下查看整个文件,以确保它下面的文本没有"
我怎样才能让我的展望在它遇到的第一个"时停止,或者如果您有另一种方法来解决我的问题,我也对此持开放态度。 任何建议不胜感激。 谢谢。
将>放弃正则表达式。这是注定的。不是XML吗?为什么不这样对待呢?
"不要使用正则表达式解析 HTML"规则同样适用于 XML。
如果你想尝试一下正则表达式,我会建议这样的东西:
<Reference[^>]*?>(?:.(?!</Reference>))*?<SpecificVersion>([^<]*?)</SpecificVersion>
它匹配所有内部有标签的标签 - 即它将完全忽略任何没有标签的引用标签。
- 它查找引用标记
- 匹配不是结束引用标记的所有内容,直到找到标记
- 然后它捕获标签
内的值
我在正则表达式中在线测试了它,它似乎在多种情况下都能正常工作。
编辑:
- 使用正则表达式选项.单行使点匹配新行
如果您想匹配根本不存在 SpecificVersion 标签的情况,请尝试此更改 - 它将尝试将选项与标签匹配,但如果失败,它仍将匹配
<Reference[^>]*?>(?:.(?!</Reference>))*?(<SpecificVersion>([^<]*?)</SpecificVersion>)|<Reference[^>]*?>(?:.(?!</Reference>))*?(?:<SpecificVersion>([^<]*?)</SpecificVersion>)?
让我知道你过得怎么样。
因此,按照spender的建议,我研究了正则表达式的替代方案。我发现了 Linq To XML,它使解决我的问题变得非常容易。 这是我结束用来解决我的问题的代码。 它在 .csproj 文件中查找对 IQ DLL 文件的所有引用,并确保它们都具有
// Let's parse us some XML!
XElement xmlFile = XElement.Load(filePath);
// Grab all of the references to DLL files.
var iqReferences = xmlFile.Descendants().Where(e => e.Name.LocalName.Equals("Reference", StringComparison.InvariantCultureIgnoreCase));
// We only care about iQ DLL files.
iqReferences = iqReferences.Where(r => r.Attribute("Include") != null && r.Attribute("Include").Value.StartsWith("IQ.", StringComparison.InvariantCultureIgnoreCase));
// If this project file doesn't reference any iQ DLL files, move on to the next project file.
if (!iqReferences.Any())
continue;
// Make sure they all have <SpecificVersion> set to False.
foreach (XElement reference in iqReferences)
{
// If this Reference element already has a child SpecificVersion element whose value is false, skip this reference since it is good.
if (reference.Elements().Where(e => e.Name.LocalName.Equals("SpecificVersion", StringComparison.InvariantCultureIgnoreCase))
.Any(e => e.Value.Equals("False", StringComparison.InvariantCultureIgnoreCase)))
continue;
// Add this reference to the list of bad references.
badReferences.AppendLine("'t" + reference.Attribute("Include").Value);
// Fix the reference.
reference.SetElementValue(reference.Name.Namespace + "SpecificVersion", "False");
}