PHP preg_replace令人困惑的错误

时间:2015-05-30 12:37:32

标签: php regex preg-replace

我有一个非常奇怪的问题,我花了很多时间而没有任何成功....我的网站上有一个令人满意的区域,用户可以选择他们可以在书面文本中立即看到的表情符号(如果是可信区域)。所以对于从用户到用户的消息,我不关心文本的长度,但是我写的是评论!我需要计算字符串的所有字符。

现在我遇到的问题是表情符号是这样传播的:

<img src="data:image/gif;base64,R0lGODlhAQABAAAAACwAAAAAAQABAAA=" class="emoticon emoticon-class-name-for-example-happy">

好的,我确实只想为每个表情符号计算一个字符,所以我写了一个正则表达式并试图用&#39; 1&#39;替换所有表情符号。之后我觉得这很简单,只有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变量,它再次起作用....无论我做什么,我的代码都没有替换单个表情符号,而文本是由用户动态传输的....

有什么地方可以想象这会出现什么问题吗? 我无能为力,我无法相信这是真的。它必须工作我尝试了很多其他事情,但没有任何作用对我来说....

3 个答案:

答案 0 :(得分:1)

包含图片的文字实际上是一个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

答案 1 :(得分:0)

将表情符号作为文本存储在数据库中是明智的。例如,幸福的面孔可以存储为:)或=),并且在数据库中只使用2个字符。

然后在输出上执行你在这里做的OPOPOSITE并使用preg_replace替换所有的:)或=)等..与相关的<img src=...

这几乎是所有Web应用程序中使用的标准。它允许您动态更改以后使用的表情符号,例如,如果您更改模板并希望表情符号也可以更改,则更改表情符号功能以及数据库中之前的所有出现也会发生变化。

这不仅可以帮助您计算字符数量,还可以帮助您管理和清理数据库。

<?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。天空成了极限。

答案 2 :(得分:0)

为什么使用var_dumpprint_r来获取用户的数据?那些函数echo输入到标准输出,它们实际上不返回字符串。看看:

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没有返回任何内容。除非你使用ob_start()ob_get_clean()之类的东西来使字符串回显到标准输出(这是一个糟糕的解决方案并且不起作用),否则你的方法将无效。您也可以将true作为第二个参数传递给print_r,以便它返回输出,但我很难理解您为什么要首先使用这些函数中的任何一个。

P.S。作为旁注,在我看来,你的正则表达式有点草率。您应该使用\s来表示空格字符,而不是[ ]。您也可以只使用而不使用括号,它会做同样的事情。此外,您不需要在最后>周围使用括号:

<img\ssrc=["'].+?["']\sclass=["']emoticon\s.+?["']>