【问题标题】:RegEx to match string only if it occurs inside a specific HTML element正则表达式仅在字符串出现在特定 HTML 元素内时才匹配字符串
【发布时间】:2015-06-15 23:40:31
【问题描述】:

我正在尝试在 Visual Studio 2013 项目中查找某些代码部分。我正在为此使用 RegEx 搜索功能(我检查了搜索选项下的“使用正则表达式”)。

更具体地说,我试图找到位于开始和结束脚本标记之间的字符串“findthis”(不带引号)。 RegEx 应该能够匹配多行字符串。

例子:

<html>
    <head>
        <script>
            var x = 1;

            if (x < 1) {
                x = 100;
            }

            var y = 'findthis'; // Should be matched
        </script>
    </head>
    <body>
        <script>
            var a = 2;
        </script>

        <h1>Welcome!</h1>
        <p>This findthis here should not be matched.</p>

        <script>
            var b = 'findthis too'; // Should be matched, too.
        </script>

        <div>
            <p>This findthis should not be matched neither.</p>
        </div>
    </body>
</html>

到目前为止我尝试过的如下((?s) 启用多行):

(?s)\<script\>.*?(findthis).*?\</script\>

这里的问题是当脚本结束标记出现时它不会停止搜索“findthis”。这就是为什么在 Visual Studio 2013 中,它还在搜索结果中的正文开始标记之后显示脚本元素。

谁能帮我摆脱这个正则表达式的地狱?

【问题讨论】:

  • 不幸的是,Regex 不适合解析 HTML。
  • 不需要对 HTML 进行严格正确的解析。我只想匹配出现在字符串 x 和字符串 y 之间的字符串。并且字符串 x 和 y 应该能够在文本中出现不同的时间。所以它应该停止在字符串 y 处搜索,我想这是这里最难的部分。
  • 你总是知道搜索词是什么标签吗?

标签: html regex visual-studio-2013


【解决方案1】:

您可以使用此正则表达式来避免匹配&lt;script&gt; 标签:

<script>((?!</?script>).)*(findthis)((?!</?script>).)*</script>

或者,使用原子分组更有效:

<script>(?>(?!</?script>).)*(findthis)(?>(?!</?script>).)*</script>

我假设我们不想匹配两者之间的打开或关闭&lt;script&gt; 标签,所以,我在(?&gt;(?!&lt;/?script&gt;).)* 中使用/?,只是为了避免任何其他格式错误的代码。我在(findthis) 之后重复一遍,这样我们只匹配后面没有&lt;script&gt;&lt;/script&gt; 的字符。

在 Expresso 中测试,输入稍作修改(我在各处添加了 &lt;&gt; 以模拟损坏):

【讨论】:

  • 这行得通,非常感谢!您能否解释一下((?!&lt;/?script&gt;).) 中的第二个问号是什么意思,以及为什么我在(findthis) 部分之后第二次需要这个指令?我很乐意将您的答案标记为已接受。
  • 我添加了我的解释。我现在几乎想不出任何格式错误的例子,这就是为什么我要谨慎行事,只匹配一对&lt;script&gt;/&lt;/script&gt;标签之间的每个字符。我愿意接受任何改进。
  • 太棒了,非常感谢您的快速帮助! @Aaron,感谢您的链接,这正是我正在寻找的解释。
【解决方案2】:

基于@Aaron 的回答:

\<script\>(?:[^<]|<(?!\/script>))*?(findthis).*?\<\/script\>

Debuggex Demo

所以你可以看到我用(?:[^&lt;]|&lt;(?!\/script&gt;)) 表示“匹配任何不是&lt;&lt; 后面没有/script&gt; 的东西”

【讨论】:

  • 对理解解决方案很有帮助。谢谢!
【解决方案3】:

也许这行得通

(?s)\<script\>[^<]*?(findthis).*?\</script\>

[^&lt;]*? 部分将避免在匹配 findthis 之前匹配另一个标签。

https://www.regex101.com/r/pV7iY6/1

【讨论】:

  • 你也应该在结束脚本标签时转义反斜杠...\&lt;\/script\&gt;
  • 这应该可以工作,除非你在你的代码中有任何比较像x &lt; 5
  • 这在某些情况下确实有效。但是我可以以某种方式扩展[^&lt;] 部分以不匹配字符串而不是单个字符吗? (我问这个是因为 JavaScript 中也经常出现左尖括号。)
  • 我已编辑我的问题以包含该特殊情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-30
  • 1970-01-01
  • 2017-10-02
相关资源
最近更新 更多