当字符串在注释中时,如何改进此正则表达式以使其不匹配

How to improve this regex to not matches when the strings are in comments

鉴于此示例文本:

<input type="text" value="<? print(variable); ?>">

<? /*<br><br><small>Data:</small>

<input type="text" value="<? print(data); ?>"> */ ?>

<textarea><? print(yuppy); ?></textarea>

要捕获 ?> 中的所有内容(一个一个),我使用:

/<\?\s*([\s\S]+?)\s*\?>/g

这个正则表达式的问题是它甚至会匹配 ?>/ * */// (评论) 并且这不是所需的行为。

当这些字符串不在评论中时,我如何改进该正则表达式以正确匹配它们?


明确地说,正确的匹配应该是:

1) print(variable);
2) /*<br><br><small>Data:</small>

<input type="text" value="<? print(data); ?>"> */
3) print(yuppy);

而不是我的正则表达式,第二个匹配项是:

/*<br><br><small>Data:</small>

<input type="text" value="<? print(data);

更新:

Josh Crozier 的答案几乎不错,但有点错误:

他的正则表达式 <\?\s*((?:.*\/\*[\s\S]+\*\/.*)|(?:[\s\S]+?))\s*\?> 错误地匹配 https://regex101.com/r/oL5iV0/2:

<? /* hello */ ?>
html
<? /* world*/ ?>

甚至 https://regex101.com/r/qW7mR7/1:

<input type="text" value="<? print(code); ?>"> <? /* */ ?>

在最新的例子中,只有在有换行符的情况下才能正确匹配。在第一个示例中,即使有换行符也无法正确匹配

您可以使用替代方法 ((?:.*\/\*[\s\S]+\*\/.*)|(?:[\s\S]+?)) 来涵盖这两种情况。

Example Here

/<\?\s*((?:.*\/\*[\s\S]+\*\/.*)|(?:[\s\S]+?))\s*\?>/g

它将尝试匹配注释之间和注释周围的所有内容 (.*\/\*[\s\S]+\*\/.*),或者匹配 ([\s\S]+?) 您最初拥有的内容。

输出:

1) print(variable);
2) /*<br><br><small>Data:</small>

<input type="text" value="<? print(data); ?>"> */
3) print(yuppy);

您可以使用此模式(删除空格和注释以使其与 javascript 一起使用):

<\?  # opening tag
[^?\/]* # all that is not a ? or a /
(?:
    \/ # a slash:
    (?:
        (?![\/*]) [^?\/]*  # - not followed by a slash or a *
      |
        \/.*(?:\n[^?\/]*)? # - that starts a single line comment
      | 
        \*                 # - that starts a multiline comment
        [^*]* (?:\*+(?!\/)[^*]*)* # (comment content)
        (?:\*\/ [^?\/]* | $)      # */ is optional
    )
  |
  \?(?!>) [^?\/]* # a ? not followed by a >
)*
(?:\?>|$) # optional closing tag ?>

demo

请注意,此模式不会导致灾难性的回溯,因为在 <\? 之后所有内容都是可选的,特别是结束标记 ?> 和多行注释的结尾 */