【问题标题】:preg_match function doesn't work correctly in certain PHP scriptpreg_match 函数在某些 PHP 脚本中无法正常工作
【发布时间】:2010-11-13 04:36:38
【问题描述】:

我正在使用 preg_match 函数从我制作的 2 个 PHP 脚本中的 textarea 表单中过滤不需要的字符,但其中一个似乎不起作用。

这是有问题的脚本:

<?php
    //Database connection, etc......

    mysql_select_db("etc", $con);
    $errmsg = '';
    $chido = $_POST['chido'];
    $gacho = $_POST['gacho'];
    $maestroid = $_POST['maestroid'];
    $comentario = $_POST['comment'];
    $voto = $_POST['voto'];

    if($_POST['enviado']==1) {
        if (preg_match ('/[^a-zA-Z áéíóúüñÁÉÍÓÚÜÑ]/i', $comentario))
            $errmsg = 1;
        if($errmsg == '') {
            //here's some queries, etc
        }
    }

    if($errmsg == 1)
        echo "ERROR: You inserted invalid characters...";
?>

所以你可以看到 preg_match 只是过滤掉不需要的字符,比如 !"#$%&/() 等等。

但每次我输入一个特殊字符,如“ñ”或“á”,都会触发错误代码。

我有这个非常相似的脚本,它可以完美地与相同的 preg_match 配合使用,并且只过滤不需要的字符:

//Database connection, etc..
mysql_select_db("etc", $con);
$errmsg = '';

if ($_POST['enviado']==1) {
     $nombre = $_POST['nombre'];
     $apodo = $_POST['apodo'];
     $mat1 = $_POST['mat1'];
     $mat2 = $_POST['mat2'];
     $mat3 = $_POST['mat3'];

     if (preg_match ('/[^a-zA-Z áéíóúüñÁÉÍÓÚÜÑ]/i', $nombre))
         $errmsg = 1;


     if($errmsg == '') {
         //more queries after validation
     }
}

if($errmsg == 1)
    echo "ERROR: etc......."
?>

所以问题是,我在第一个脚本中做错了什么?

我尝试了所有方法,但总是失败并显示错误。

有什么建议吗?

【问题讨论】:

  • 在使用preg_match 测试之前打印$comentario 的值,确保它包含您认为它包含的内容。在不知道您使用的输入的情况下,我们无法为您调试。
  • 我在第一个 IF 之前和之后回显了变量,并准确打印了我输入的内容,包括“ñ”等。此外,当我向 preg_match 添加内容时,例如 0-9 似乎正确的更改并且不过滤数字,唯一的问题实际上只发生在像“ñ”这样的特殊字符上。
  • 这可能与客户端和源中的不同字符集有关。
  • @jcomeau 我错过了字符类开头的'^',感谢您指出这一点,我的回答没有多大意义。
  • 我将此添加到表单
    中。现在好像可以了,很奇怪。

标签: php regex utf-8 preg-match unicode-normalization


【解决方案1】:

尝试在末尾添加一个 u 以及你的 i 以使用 unicode

/[^a-zA-Z áéíóúüñÁÉÍÓÚÜÑ]/iu

【讨论】:

  • $nombre = "(adsfá"; if (preg_match ('/[^a-zA-Z áéíóúüñÁÉÍÓÚÜÑ]/iu', $nombre)) echo "match!"; 为我工作.. .
  • 是的,它可以工作,但现在可以接受任何字符,例如 !"#$%&/()=? 等。我不想要这些字符。
【解决方案2】:

在我使用这个匹配表达式之前你好:

/^[a-z]\d_]+$/i

因为 i 接受从 a 到 z 的字母、从 0 到 9 的数字和下划线“_”、加号“+”以重复整个字符串,以及“/i”用于不敏感匹配。但我需要接受 'ñ' 字母。

所以,我尝试并为我工作的是使用这个正则表达式:

/^[a-z\d_\w]+$/iu

我添加了 '\w' 以接受任何单词字符,并在 '/i' 之后添加了一个 'u' 以将模式视为 UTF-16 字符集,而不是 UTF-8。

【讨论】:

    【解决方案3】:

    这可能会有所帮助:http://www.phpwact.org/php/i18n/charsets

    【讨论】:

      【解决方案4】:

      我已将此添加到表单中。

      <form accept-charset="utf-8">. 
      

      现在看来可以了。

      【讨论】:

        【解决方案5】:

        为什么要指定/i 却要分别枚举所有的大写和小写字母?

        另外:如果您不对输入进行规范化,这根本行不通。考虑一下ñ 可以是字符 U+F1 字符 U+4E 后跟 U+303!

        • Unicode 规范化形式 D 将保证 U+F1 和 U+4E,U+303 都变成规范分解的形式 U+4E,U+303。

        • Unicode 规范化表格 C 将保证 U+F1 和 U+4E,U+303 都变成 U+4E 形式,因为它使用规范分解,然后是规范组合。 p>

        根据您的模式,您似乎需要 NFC 表单。

        在 PHP 中,您需要在这些上使用 Normalization class 才能使其可靠地工作。

        【讨论】:

        • 我知道 /i 在示例中没有用,但仅用于演示目的(根本不影响我的 preg_match)。无论如何,我已经解决了添加到我的 html 表单
          的问题。我不知道为什么这解决了这个问题,我在第二个脚本中使用的另一种形式没有这个属性并且可以正常工作。
        【解决方案6】:

        我不知道这是否有帮助,但我对那些特殊字符有完全相同的问题,这让我疯狂了很多天最后我明白问题是一个 html_entities() 命令清理字符串在 preg_match() 中运行之前,将 html_entities() 移到 prey_match() 之后使其工作得很好。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2016-08-11
          • 1970-01-01
          • 2015-01-27
          • 1970-01-01
          • 2012-05-13
          • 2018-09-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多