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;
?>

View In Action

显然,您甚至可以将其调整为使用数据库来管理您的表情符号,并使用数组来 运行 pregreplace。天空成为极限。

为什么要使用 var_dumpprint_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