PHP preg_replace 混淆错误
PHP preg_replace Confusing error
我有一个非常奇怪的问题,我花了很多时间但没有任何成功...。我的网站上有一个 contenteditable 区域,用户可以在其中 select 表情符号,他们可以在他们的书面文本中立即看到这些表情符号(如果是 contenteditable 区域)。因此,对于用户之间的消息,我不关心文本的长度,但我关心写评论!我需要计算字符串的所有字符。
我现在遇到这样的问题:
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon emoticon-class-name-for-example-happy">
好吧,我当然想为每个表情符号只计算 1 个字符,所以我写了一个正则表达式并尝试用“1”替换所有表情符号。后来我认为只用 strlen 就可以很容易地得到使用的字符数。
但这仅在理论上有效,但该死的为什么......
所以我的正则表达式是:
<img[ ]src=["'].+?["'][ ]class=["']emoticon[ ].+?["'][>]
下一点是我开始在 phpliveregex.com 的帮助下测试我的正则表达式。结果你可以看到here。只需单击 preg_replace 选项卡。
现在我很确定这对我有用,我试过了。我在 PHP:
中写了一个函数
private function countCharactersOfSpecialUserInput($userInput) {
$wholeCharacters = 0;
$input_lines = 'This is a test
for<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex
which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should
be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">
match all this emoticons except things like <img dsopjfdojp
<img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">
';
return preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", $input_lines);
}
在我的函数中,我现在不计算字符数,因为有一个我不明白的错误。这听起来不可能,但它是真实的:-(.
如果我使用保存在变量 $input_lines 中的字符串,它会很好地工作。但是,如果我使用用户可以传输的文本,它就不起作用!
我使用了var_dump和print_r来获取用户传输的数据。之后我完全使用了这个字符串并将其保存在 input_lines 变量中。令人难以置信的事实是,通过使用 input_lines 变量,它再次起作用了……。不管我做什么我的代码都不会替换单个表情符号,而文本是由用户动态传输的...。
有什么你能想象到会导致这个问题的地方吗?
我一无所知,我不敢相信这是真的。它必须起作用,我尝试了很多其他的方法,但对我没有任何作用......
您最好将表情符号作为文本存储在数据库中。例如,一张笑脸可以存储为 :) 或 =),并且在您的数据库中只用完 2 个字符。
然后在输出上执行与您在此处所做的相反的操作,并使用 preg_replace
将 :) 或 =) 等的所有实例替换为相关的 <img src=...
这几乎是所有网络应用的标准。它将允许您动态更改您以后使用的表情符号,例如,如果您更改模板并希望表情符号也更改,您更改您的表情符号功能,并且数据库中所有先前出现的事件也会更改。
这不仅可以帮助您计算字符数,还可以帮助您将来管理和清理数据库。
<?php
$input = 'Hello There! :) How are you today?';
$happy = '<img src="img/smile.gif" border="0" />';
$output = preg_replace("(\:\))", $happy, $input);
echo $output;
?>
显然,您甚至可以将其调整为使用数据库来管理您的表情符号,并使用数组来 运行 pregreplace。天空成为极限。
为什么要使用 var_dump
和 print_r
从用户那里获取数据?这些函数 echo
输入到标准输出,它们实际上不是 return 字符串。看看:
php > $num_finds = preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", $lines);
php > echo($num_finds);
1my1regex which1should be alright 1and1 match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: 1
工作正常。但是,如果您尝试使用 var_dump,您会得到:
php > $dump_num_finds = preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", var_dump($lines));
string(718) "<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking"> match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">"
php > echo $dump_num_finds;
同样,原因是 var_dump
没有 return 任何东西。除非您使用 ob_start()
和 ob_get_clean()
之类的东西来使字符串回显到标准输出(imo 是一个糟糕的解决方案,不会起作用),否则您的方法将不起作用。您还可以将 true
作为第二个参数传递给 print_r
以将其传递给 return 输出,但我无法理解为什么您首先要使用这些函数中的任何一个.
P.S。作为旁注,在我看来,您的正则表达式有点草率。您应该使用 \s
来表示空白字符而不是 [ ]
。您也可以只使用不带括号的 </code> ,它会做同样的事情。此外,您不需要最后 <code>>
:
周围的括号
<img\ssrc=["'].+?["']\sclass=["']emoticon\s.+?["']>
带图片的文字实际上是 HTML 片段,因此我会使用 DOM
来解析它:
$input_lines = 'This is a test for<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking"> match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">';
$doc = new DOMDocument();
// Suppress warnings
@$doc->loadHTML($input_lines);
$imgs = $doc->getElementsByTagName("img");
$number_of_imgs = $imgs->length;
echo "Found $number_of_imgs images" . PHP_EOL;
// The plain text is actually the nodeValue of
// the whole snippet.
$text = $imgs->item(0)->parentNode->nodeValue;
$len = mb_strlen($text);
echo "Text length: $len + $number_of_imgs(images)" . PHP_EOL;
看到它有效:http://3v4l.org/MH5T6
我有一个非常奇怪的问题,我花了很多时间但没有任何成功...。我的网站上有一个 contenteditable 区域,用户可以在其中 select 表情符号,他们可以在他们的书面文本中立即看到这些表情符号(如果是 contenteditable 区域)。因此,对于用户之间的消息,我不关心文本的长度,但我关心写评论!我需要计算字符串的所有字符。
我现在遇到这样的问题:
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon emoticon-class-name-for-example-happy">
好吧,我当然想为每个表情符号只计算 1 个字符,所以我写了一个正则表达式并尝试用“1”替换所有表情符号。后来我认为只用 strlen 就可以很容易地得到使用的字符数。 但这仅在理论上有效,但该死的为什么......
所以我的正则表达式是:
<img[ ]src=["'].+?["'][ ]class=["']emoticon[ ].+?["'][>]
下一点是我开始在 phpliveregex.com 的帮助下测试我的正则表达式。结果你可以看到here。只需单击 preg_replace 选项卡。
现在我很确定这对我有用,我试过了。我在 PHP:
中写了一个函数private function countCharactersOfSpecialUserInput($userInput) {
$wholeCharacters = 0;
$input_lines = 'This is a test
for<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my
<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex
which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should
be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">
match all this emoticons except things like <img dsopjfdojp
<img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">
';
return preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", $input_lines);
}
在我的函数中,我现在不计算字符数,因为有一个我不明白的错误。这听起来不可能,但它是真实的:-(.
如果我使用保存在变量 $input_lines 中的字符串,它会很好地工作。但是,如果我使用用户可以传输的文本,它就不起作用!
我使用了var_dump和print_r来获取用户传输的数据。之后我完全使用了这个字符串并将其保存在 input_lines 变量中。令人难以置信的事实是,通过使用 input_lines 变量,它再次起作用了……。不管我做什么我的代码都不会替换单个表情符号,而文本是由用户动态传输的...。
有什么你能想象到会导致这个问题的地方吗? 我一无所知,我不敢相信这是真的。它必须起作用,我尝试了很多其他的方法,但对我没有任何作用......
您最好将表情符号作为文本存储在数据库中。例如,一张笑脸可以存储为 :) 或 =),并且在您的数据库中只用完 2 个字符。
然后在输出上执行与您在此处所做的相反的操作,并使用 preg_replace
将 :) 或 =) 等的所有实例替换为相关的 <img src=...
这几乎是所有网络应用的标准。它将允许您动态更改您以后使用的表情符号,例如,如果您更改模板并希望表情符号也更改,您更改您的表情符号功能,并且数据库中所有先前出现的事件也会更改。
这不仅可以帮助您计算字符数,还可以帮助您将来管理和清理数据库。
<?php
$input = 'Hello There! :) How are you today?';
$happy = '<img src="img/smile.gif" border="0" />';
$output = preg_replace("(\:\))", $happy, $input);
echo $output;
?>
显然,您甚至可以将其调整为使用数据库来管理您的表情符号,并使用数组来 运行 pregreplace。天空成为极限。
为什么要使用 var_dump
和 print_r
从用户那里获取数据?这些函数 echo
输入到标准输出,它们实际上不是 return 字符串。看看:
php > $num_finds = preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", $lines);
php > echo($num_finds);
1my1regex which1should be alright 1and1 match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: 1
工作正常。但是,如果您尝试使用 var_dump,您会得到:
php > $dump_num_finds = preg_replace("/<img[ ]src=[\"'].+?[\"'][ ]class=[\"']emoticon[ ].+?[\"'][>]/", "1", var_dump($lines));
string(718) "<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking"> match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">"
php > echo $dump_num_finds;
同样,原因是 var_dump
没有 return 任何东西。除非您使用 ob_start()
和 ob_get_clean()
之类的东西来使字符串回显到标准输出(imo 是一个糟糕的解决方案,不会起作用),否则您的方法将不起作用。您还可以将 true
作为第二个参数传递给 print_r
以将其传递给 return 输出,但我无法理解为什么您首先要使用这些函数中的任何一个.
P.S。作为旁注,在我看来,您的正则表达式有点草率。您应该使用 \s
来表示空白字符而不是 [ ]
。您也可以只使用不带括号的 </code> ,它会做同样的事情。此外,您不需要最后 <code>>
:
<img\ssrc=["'].+?["']\sclass=["']emoticon\s.+?["']>
带图片的文字实际上是 HTML 片段,因此我会使用 DOM
来解析它:
$input_lines = 'This is a test for<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">my <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">regex which<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">should be alright <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking">and<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Not-Talking"> match all this emoticons except things like <img dsopjfdojp <img oew> because this ones are not real emoticons! The following is a real one: <img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon Girl">';
$doc = new DOMDocument();
// Suppress warnings
@$doc->loadHTML($input_lines);
$imgs = $doc->getElementsByTagName("img");
$number_of_imgs = $imgs->length;
echo "Found $number_of_imgs images" . PHP_EOL;
// The plain text is actually the nodeValue of
// the whole snippet.
$text = $imgs->item(0)->parentNode->nodeValue;
$len = mb_strlen($text);
echo "Text length: $len + $number_of_imgs(images)" . PHP_EOL;
看到它有效:http://3v4l.org/MH5T6