0

我正在从事一个已经开发了大约 20 年的大型项目,而且规模巨大。需要对大约 300 页进行修改,实际替换大约 2800 个。这让我渴望使用 Visual Studio 的 RegEx 进行实际替换。

它位于另一种文件类型的伪 HTML 文件中,该文件被传递给基于某些命令“执行”代码并输出 HTML 文本的解析器。我正在使用的语法包含带有如下调用的常规 HTML 代码:

<div id="outer-box" <__@BGCOLOR>>            //Basic call
<div id="outer-box" <__@BGCOLOR TOGGLE"1">>  //Call with toggle (only) parameter

现在我需要做的就是将其更改为:

<div id="outer-box" style="<__@BGCOLOR>">
<div id="outer-box" style="<__@BGCOLOR TOGGLE="1">">

但这就是问题所在。一些标签已经声明了 style 属性,如下所示:

<div id="inner-box" style="border:1px" <__@BGCOLOR>>  //One possibility
<div id="inner-box" <__@BGCOLOR> style="border:1px">  //Another one

这意味着我需要将其更改为:

<div id="inner-box" style="<__@BGCOLOR>border:1px">

我已经与它战斗了几个小时,但似乎无法做到正确。我还应该补充一点,有时一行中会出现多个 HTML 元素,有时在给定元素中会出现多个解析器调用(使用与 BGCOLOR 不同的命令)。

到目前为止,我找到的所有尚未修复的实例是这样的:

~(style=")\<__\@BGCOLOR{.@}\>



编辑:为澄清起见,这是使用Visual Studio 的 RegEx 语法,我正在专门寻找对 BGCOLOR 命令的调用。我有上面的正则表达式,它能够找到 <__@BGCOLOR[ TOGGLE="1"]> 之前没有'style="' 的所有情况,以过滤掉已经修复的项目。

4

2 回答 2

2

我将首先对文本做一些简化的假设。在尝试将 HTML 与正则表达式匹配时,这总是必要的,但在这种情况下,主要是为了使正则表达式更易于阅读。可以更正正则表达式以反映更复杂的标准,而无需更改其基本结构。

  • 元素和属性名称总是按字母顺序排列(即,它们与 VS 的:w, 或匹配[A-Za-z]+)。
  • 属性名称前面总是有空格和/或制表符 ( :b+)。
  • 属性值始终用引号引起来 ( :q)。
  • =属性名称和它的值之间没有空格。

另外,请注意我在~(style):w. 它说“一个或多个字母 ( :w),但如果它们构成单词,则不是style”。您正在使用它,就好像它是一个否定的视:" <__@BGCOLOR{.@}>,除非它前面是style="。很多人都会犯这个错误。

我提出了一个四步流程:

首先,匹配任何带有特殊标记的元素并重新排列它,以便将标记列在所有属性之后:

  • 搜索:{\<:w(:b+:w=:q)*}{:b+\<__\@BGCOLOR[^<>]*\>}{(:b+:w=:q)+}
  • 代替:\1\3\2

其次,如果有一个style属性,请确保它是列出的最后一个属性(但在特殊标记之前):

  • 搜索:{\<:w(:b+~(style):w=:q)*}{:b+style=:q}{(:b+~(style):w=:q)+}{:b+\<__\@BGCOLOR[^<>]*\>}
  • 代替:\1\3\2\4

第三,将特殊标记包装在一个style属性中:

  • 搜索:{\<__\@BGCOLOR[^<>]*\>}\>
  • 代替:style="\1">

最后,如果有两个style属性,合并它们:

  • 搜索:style="{[^"]+}":b+style="{\<[^<>]+\>}"
  • 代替:style="\1; \2"

从这段文字开始:

<div <__@BGCOLOR> id="inner-box" style="border:1px">
<div foo="bar" id="inner-box" <__@BGCOLOR TOGGLE="1"> style="border:1px">
<div id="inner-box" bar="foo" <__@BGCOLOR>>
<div  id="inner-box" <__@BGCOLOR> style="border:1px">
<div id="inner-box" style="border:1px" <__@BGCOLOR TOGGLE="1">>
<div id="inner-box" <__@BGCOLOR> foo="bar">

...我最终得到了这个:

<div id="inner-box" style="border:1px; <__@BGCOLOR>">
<div foo="bar" id="inner-box" style="border:1px; <__@BGCOLOR TOGGLE="1">">
<div id="inner-box" bar="foo" style="<__@BGCOLOR>">
<div  id="inner-box" style="border:1px; <__@BGCOLOR>">
<div id="inner-box" style="border:1px; <__@BGCOLOR TOGGLE="1">">
<div id="inner-box" foo="bar" style="<__@BGCOLOR>">

我得告诉你,Visual Studio 是这里的主要障碍。这是一个很棒的 IDE,但它的正则表达式风格很奇怪。如果您打算做很多此类事情,我强烈建议您切换到像EditPad ProPowerGrep这样的工具,它使用标准语法的全功能正则表达式风格。

编辑:我终于做了(相对)明智的事情,并以类似 Perl 的风格编写了正则表达式,主要是为了找出问题是否可以用正则表达式解决。确实如此,而且只需要两个步骤:

搜索:

(
  <\w+\b
  (?:
    \s*
    (?:
      \w+="[^"]+"
    |
      <(?!__@BGCOLOR)[^<>]*>
    )
  )*
  \s*
)
(<__@BGCOLOR[^<>]*>)
(
  (?:
    \s*
    (?:
      \w+="[^"]+"
    |
      <[^<>]+>
    )
  )*
)

代替:

$1style="$2"$3

搜索:

(
  <\w+\b
  (?:
    \s*
    (?:
      (?!style)\w+="[^"]+"
    |
      <[^<>]+>
    )
  )*
  \s*
)
style="([^"]+)"
(
  (?:
    \s*
    (?:
      (?!style)\w+="[^"]+"
    |
      <[^<>]+>
    )
  )*
)
\s*style="([^"]+)"

代替:

$1style="$2; $4"$3

下一步是将其转换为 Visual Studio 语法(如果可能的话),但我现在太累了,无法开始。;) 而且,正如我之前所说,如果你要经常做这种事情,你应该考虑编写一个专用的解析器,或者切换到使用标准语法的工具或语言(对于非常松散的定义“标准”)。无论您做什么,都不要使用 Visual Studio 的本机所谓的正则表达式,您将对每个人都有帮助。:D

于 2012-07-03T04:21:39.343 回答
0

这是我想出的(任何人都可以自由编辑):

正则表达式:^.*<.*(<.*>(?!")).*>.*$

那应该捕获该<__@BGCOLOR>区域,然后您可以将其替换为适合您需要的任何内容。

于 2012-07-03T00:54:14.260 回答