我有这个 HTML:
“这是简单的 html 文本 文本”
我只需要匹配脚本标签之外的单词。我的意思是,如果我想匹配“simple”和“text”,我应该只从“This is simple html text”和最后一部分“text”得到结果——结果将是“simple”1匹配,“text”2火柴。谁能帮我解决这个问题?我正在使用 PHP。
我在标签外找到了匹配文本的类似答案:
(text|simple)(?![^<]*>|[^<>]*</)
但无法为特定标签(脚本)工作:
(text|simple)(?!(^<script*>)|[^<>]*</)
ps:此题不重复(strip_tags,去掉javascript)。因为我不是要剥离标签,或选择脚本标签内的内容。我正在尝试替换标签“脚本”之外的内容。
我的模式将使用
(*SKIP)(*FAIL)
取消匹配的脚本标签及其内容的资格。
text
和 simple
将在每次符合条件的情况下匹配。
正则表达式模式:
~<script.*?/script>(*SKIP)(*FAIL)|text|simple~
代码:(演示)
$strings=['This has no replacements',
'This simple text has no script tag',
'This simple text ends with a script tag <script language="javascript">simple simple text text</script>',
'This is simple html text is split by a script tag <script language="javascript">simple simple text text</script> text',
'<script language="javascript">simple simple text text</script> this text starts with a script tag'
];
$strings=preg_replace('~<script.*?/script>(*SKIP)(*FAIL)|text|simple~','***replaced***',$strings);
var_export($strings);
输出:
array (
0 => 'This has no replacements',
1 => 'This ***replaced*** ***replaced*** has no script tag',
2 => 'This ***replaced*** ***replaced*** ends with a script tag <script language="javascript">simple simple text text</script>',
3 => 'This is ***replaced*** html ***replaced*** is split by a script tag <script language="javascript">simple simple text text</script> ***replaced***',
4 => '<script language="javascript">simple simple text text</script> this ***replaced*** starts with a script tag',
)
如果确定
script
将出现,那么只需匹配
(.*?)<script.*</script>(.*)
标签外的文本将出现在子匹配 1 和 2 中。如果
script
是可选的,那么执行 (.*?)(<script.*</script>)?(.*)
.
仅供参考,就标签而言,不可能忽略单个标签
无需解析所有标签。
您可以跳过/失败过去的html标签和不可见的内容。
这将找到您要查找的单词。
'~<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|\'[\S\s]*?\'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\1\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|\'[\S\s]*?\'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>(*SKIP)(?!)|(?:text|simple)~'
https://regex101.com/r/7ZGlvW/1
格式化
<
(?:
(?:
(?:
# Invisible content; end tag req'd
( # (1 start)
script
| style
| object
| embed
| applet
| noframes
| noscript
| noembed
) # (1 end)
(?:
\s+
(?>
" [\S\s]*? "
| ' [\S\s]*? '
| (?:
(?! /> )
[^>]
)?
)+
)?
\s* >
)
[\S\s]*? </ \1 \s*
(?= > )
)
| (?: /? [\w:]+ \s* /? )
| (?:
[\w:]+
\s+
(?:
" [\S\s]*? "
| ' [\S\s]*? '
| [^>]?
)+
\s* /?
)
| \? [\S\s]*? \?
| (?:
!
(?:
(?: DOCTYPE [\S\s]*? )
| (?: \[CDATA\[ [\S\s]*? \]\] )
| (?: -- [\S\s]*? -- )
| (?: ATTLIST [\S\s]*? )
| (?: ENTITY [\S\s]*? )
| (?: ELEMENT [\S\s]*? )
)
)
)
>
(*SKIP)
(?!)
|
(?: text | simple )
或者,一种更快的方法是匹配两个标签AND你的文本
寻找。
匹配标签移动过去。
如果您正在进行替换,请使用回调来确定要替换的内容。
第 1 组是 TAG 或 Invisible Content run.
第 3 组是您要替换的词。
因此,在回调中,如果第 1 组匹配,则返回第 1 组。
如果第 3 组匹配,请替换为您想要替换的内容。
正则表达式
'~(<(?:(?:(?:(script|style|object|embed|applet|noframes|noscript|noembed)(?:\s+(?>"[\S\s]*?"|\'[\S\s]*?\'|(?:(?!/>)[^>])?)+)?\s*>)[\S\s]*?</\2\s*(?=>))|(?:/?[\w:]+\s*/?)|(?:[\w:]+\s+(?:"[\S\s]*?"|\'[\S\s]*?\'|[^>]?)+\s*/?)|\?[\S\s]*?\?|(?:!(?:(?:DOCTYPE[\S\s]*?)|(?:\[CDATA\[[\S\s]*?\]\])|(?:--[\S\s]*?--)|(?:ATTLIST[\S\s]*?)|(?:ENTITY[\S\s]*?)|(?:ELEMENT[\S\s]*?))))>)|(text|simple)~'
https://regex101.com/r/7ZGlvW/2
这个正则表达式类似于 SAX 和 DOM 解析器解析标签的方式。
我已经在 SO 上发布了数百次。
以下是如何删除所有 html 标签的示例: