【问题标题】:Regex to find missing quote正则表达式查找丢失的报价
【发布时间】:2021-12-02 06:00:45
【问题描述】:

只有当内容缺少开头引号或结尾引号时,我才需要一个 perl 正则表达式来选择内容。开头的引号总是以等号 = 开头。结束引号后面可以跟一个空格、更多文本或回车。在一个给定的行中,可以检查许多属性(引号对)。

我试过(?<!")(.*?)",但那是一场灾难。我想也许我可以做一个简单的正则表达式找到 equle 符号,查看下一个字符并检查它是否是引号,后跟文本和结束引号。但如果文本的开头或结尾没有引号,请添加它。

要注意引号之间的文本始终是字符数据。不会有符号或空格。

<table pgwide="0" id="dvr_config_firmware>
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1>
<colspec colname="col2">

【问题讨论】:

  • 您将如何处理包含不成对引号的 cdata,例如 &lt;title&gt;This text talks about quote marks (")&lt;/title&gt;?正确处理丢失的引号需要一个成熟的 XML 解析器,它具有良好的错误恢复能力,即使这样,它仍然会被病态的例子绊倒。这不是一个容易解决的问题。

标签: regex ultraedit


【解决方案1】:

1。在没有空格的属性值上添加缺少的结束引号

问题首先是关于纠正无效的 XML 块

<table pgwide="0" id="dvr_config_firmware>
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1>
<colspec colname="col2">

到有效的 XML 块

<table pgwide="0" id="dvr_config_firmware">
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1">
<colspec colname="col2">

UltraEdit for Windows 版本 28.20.0.70 和 UEStudio 版本 21.10.0.24 是当前使用 Boost 库的 Perl 正则表达式引擎的最新版本。

sln’s answer 中建议的 Perl 兼容正则搜索表达式是:

=(?|(")([^"<>\s]*)()(?=[\s>]|\/>)|(?!")()([^"<>\s]*)("))

它使用 UE v28.20.0.70 和 UES v21.10.0.24 以及其他一些不太旧的旧版本作为替换字符串 ="$2" 产生正确的结果。

具有搜索表达式的 Python 兼容变体

=(?:(")([^"<>\s]*)()(?=[\s>]|\/>)|(?!")()([^"<>\s]*)("))

sln 建议的替换字符串="\2\5" 一起使用也适用于当前最新版本和以前版本的UE/UES 示例数据。

2。在带有空格的属性值上添加缺少的结束引号

JennyP 在评论中写道,XML 文件还可以包含一个属性值,其中包含缺少结束引号的空格,就像在这个 XML 示例块中一样:

<table pgwide="0" id="dvr_config_firmware>
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1>
<colspec colname="col2">
<info date="09 JAN 2000 version="1.0">

现在的预期结果是:

<table pgwide="0" id="dvr_config_firmware">
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1">
<colspec colname="col2">
<info date="09 JAN 2000" version="1.0">

但是 sln 建议的 Perl 语法中的前两个正则表达式产生:

<table pgwide="0" id="dvr_config_firmware">
<title>DFR Firmware</title>
<tgroup cols="2">
<colspec colname="col1">
<colspec colname="col2">
<info date="09" JAN 2000 version="1.0">

" 中只包含日期中的某天,而不是整个日期,因为这两个正则表达式不是为具有一个或多个空格的属性值设计的,因为最初没有要求。

sln 建议的 Perl 兼容解决方案是使用搜索表达式

=(?|(")((?:(?![a-z]*=)[^"<>])*)()(?=[\s>]|/>)|(?!")()((?:(?![a-z]*=)[^"<>])*)("))

="\2" 作为替换表达式字符串,这会导致在预期结果上使用 UE/UES 执行。

使用 Python 兼容的搜索表达式结果也是正确的

=(?:(")((?:(?![a-z]*=)[^"<>])*)()(?=[\s>]|/>)|(?!")()((?:(?![a-z]*=)[^"<>])*)("))

使用替换字符串="\2\5"

@sln,干得好!

3。在带有空格的属性值上添加缺少的引号

与此同时,UltraEdit 论坛主题Regular expression to search for attributes with missing a quote 也讨论了相同的任务。

我在 UltraEdit 论坛上发布了一个更错误的 XML 块的回复:

<table pgwide=0" id="dvr_config_firmware>
<title>DFR Firmware</title>
<tgroup cols="3">
<colspec colname=col1>
<colspec colname="col2">
<colspec colname="col3 attrib="xyz">
<applicdef verdate="18 Jan 2019 verstatus="ver">

第一个属性pgwide 错过了开头的引号。属性值col1 根本没有用引号引起来。属性值 col3 错过了结束引号,接下来还有一个属性,最后一个 XML 元素也是这种情况,其属性值带有空格和缺少结束引号。

预期的 XML 块是:

<table pgwide="0" id="dvr_config_firmware">
<title>DFR Firmware</title>
<tgroup cols="3">
<colspec colname="col1">
<colspec colname="col2">
<colspec colname="col3" attrib="xyz">
<applicdef verdate="18 Jan 2019" verstatus="ver">

第二章中 sln 建议的 Perl 和 Python 兼容表达式可以很好地为那些在开头或结尾缺少一个的属性值添加引号。但是属性值col1 没有用引号括起来。这当然不是任务的要求。

我建议使用两个 Perl 兼容的正则表达式替换来获得预期的结果:

  1. 使用\w=\K([^"=&gt;]+)(?=&gt;) 搜索并使用"$1""\1" 作为替换字符串,将这些属性值括在引号中,同时缺少两个引号,例如col1
  2. 使用 \w=\K(?:(?!")|"[^"&gt;]*\K(?=&gt;)|"[^ &gt;"]++(?= \w+=)\K|"(?:[^ &gt;"]++(?![&gt;"])(?! \w+=) )+[^ "&gt;]+\K) 搜索并仅使用 " 在仅缺少一个引号的属性值的开头或结尾插入缺少的引号。

UltraEdit 论坛成员 Fleggy 发布了另一个解决方案,它使用条件 Perl 兼容正则表达式和搜索字符串 \w=\K(")?([\w ]+)(?(1)(?!")|"?)(?!\w*[="]) 并替换字符串 "\2",这也适用于 Notepad++。

4。在带有空格的属性值上添加安全缺失的引号

上面写的所有正则表达式都有一个问题:
他们还可以修改用引号括起来的属性值。

示例:XML 块已经是:

<table pgwide="0" id="dvr_config_firmware">
<title>DFR Firmware</title>
<tgroup cols="3">
<colspec colname="col1">
<colspec colname="col2">
<colspec colname="col3" attrib="xyz">
<applicdef verdate="18 Jan 2019" verstatus="ver">

正则表达式替换的使用不应导致对该块的任何修改。但是上面的正则表达式都没有替换在这个块上执行。属性值18 Jan 2019 会导致插入另一个",这使得 XML 块对 XML 解析器无效。

但是感谢Fleggy,还有一种解决方案可以在属性值上添加安全缺失的引号,这些属性值可以有空格,并且在开头或结尾或两边都缺少引号而正确引用的属性值不会以任何方式修改。

此任务的最终 Perl 兼容正则搜索表达式是:

\w=\K(")?([\w ]+)(?(1)(?(?=")(*SKIP)(*FAIL))|"?)(?!\w*=)

替换表达式字符串为:"\2"

谢谢你,Fleggy

【讨论】:

  • 正则表达式效果很好!感谢您花时间详细解释这一切。
【解决方案2】:

使用分支重置 (?| ... ) (Perl),您可以匹配信息表单
并使用简单的替换。
这将匹配两个缺少的表单之一。

/=(?|(")([^"<>\s]*)()(?=[\s>]|\/>)|(?!")()([^"<>\s]*)("))/

替换为="$2"

https://regex101.com/r/2qvpLr/1

 = 
 (?|
    ( " )                         # (1)
    ( [^"<>\s]* )                 # (2)
    ( )                           # (3)
    (?= [\s>] | /> )
  | 
    (?! " )
    ( )                           # (1)
    ( [^"<>\s]* )                 # (2)
    ( " )                         # (3)
 )

非分支重置方式(Python):

r'=(?:(")([^"<>\s]*)()(?=[\s>]|\/>)|(?!")()([^"<>\s]*)("))'

替换为="\2\5"

https://regex101.com/r/IXFJb6/1

 = 
 (?:
    ( " )                         # (1)
    ( [^"<>\s]* )                 # (2)
    ( )                           # (3)
    (?= [\s>] | /> )
  | 
    (?! " )
    ( )                           # (4)
    ( [^"<>\s]* )                 # (5)
    ( " )                         # (6)
 )

------------------

回应评论中的@JennyP新情况:
a condition that must be in account which I wasn't told before. The attribute group can have spaces in it. For instanct &lt;info date="09 JAN 2000 version="1.0"&gt; there needs to be a quote after 2000.

可以做到,因为它不是xml/html,也不是一个属性关联
带有解析标记。

因为这些正则表达式只是解析您在
中介绍的原始字符串 你的问题。

你不能把这个问题变成“如何解析 xml/html”。
所以保持它只匹配原始的、有点形成的文本。

对于 Perl:

=(?|(")((?:(?![a-z]*=)[^"<>])*)()(?=[\s>]|/>)|(?!")()((?:(?![a-z]*=)[^"<>])*)("))

https://regex101.com/r/hXNBSx/1

对于 Python:

=(?:(")((?:(?![a-z]*=)[^"<>])*)()(?=[\s>]|/>)|(?!")()((?:(?![a-z]*=)[^"<>])*)("))

https://regex101.com/r/U4sBOW/1

【讨论】:

  • 您添加空组以保持分支重置的组数相同,以便组 2 始终包含相同的数据,对吗?
  • @Thefourthbird 没错。一些引擎抛出异常并期望每个分支中捕获组的确切数量。它通常在编译正则表达式时抛出。不确定哪些引擎(肯定是 Boost)。
  • 这是一个有趣的技术,值得记住++
  • 非常感谢您的意见。正则表达式效果很好!但是我发现了一个必须考虑的情况,这是我以前没有被告知的。属性组中可以有空格。对于即时 需要在 2000 之后有一个引号。因此新规则将检查在新属性声明或 > 之前是否缺少引号。当前 REGEX 找到“09但因为空间而停了下来。
  • @JennyP - 添加了更新(最后)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-08-22
  • 1970-01-01
  • 1970-01-01
  • 2014-08-01
  • 2013-11-10
  • 1970-01-01
  • 2011-11-19
相关资源
最近更新 更多