【问题标题】:Is my preg_match syntax valid?我的 preg_match 语法有效吗?
【发布时间】:2010-07-14 12:49:46
【问题描述】:

我正在向我的数据库抽象层添加一个 if 语句,以挑选出对少数数据库表的任何尝试查询。

基本上,如果我的应用程序尝试从名为membersmembers_profiles 的数据库表中创建、读取或销毁数据,我想调用我的if 语句。

if (
    preg_match('/INSERT INTO [members|members_profiles]/', $sql) ||
    preg_match('/UPDATE [members|members_profiles]/', $sql) ||
    preg_match('/DELETE FROM [members|members_profiles]/', $sql))
{
    // do if statement stuff here...
}

我不是正则表达式/预匹配大师,但如果 SQL 查询匹配,上述 if 语句是否会返回 true:

  • INSERT INTO members ...INSERT INTO members_profiles ...
  • UPDATE members ...UPDATE members_profiles ...
  • DELETE FROM members ...DELETE FROM members_profiles ...

或者我的预赛语法有问题?

【问题讨论】:

    标签: php regex preg-match


    【解决方案1】:

    语法是有效的,但不会做你想做的事。

    对于模式的交替,使用

    preg_match('/INSERT INTO (?:members|members_profiles)/', $sql) ||
    //                       ^^^                        ^
    

    在 PCRE 中,[…] 定义了一个字符类。这将匹配 1 个字符,因为它出现在括号内。在您的情况下,[members|members_profiles] 将匹配 1 个字符,如果它是 befilmor、@987654 之一、s|_

    使用另一种括号 (?:…) 进行分组。


    (顺便说一句,请不要使用正则表达式来检测数据库更改尝试。改为限制数据库用户的权限。)

    【讨论】:

    • 这可能需要\b 在组的末尾,并且会受益于\s* 的空格 - 尽管您关于不使用正则表达式获取权限的观点当然是有效的。
    • 我没有使用上述方法来限制数据库访问,而是更多地用于捕获对即将弃用的表的任何引用,因为我们目前正在推出一个新环境。这将在测试环境中使用一两周,以检查我们应用程序模型中的所有查询是否已更新。
    【解决方案2】:

    一个正则表达式就足够了:

    if (preg_match('/(?i)(INSERT\s+INTO|UPDATE|DELETE\s+FROM)(?-i)\s+(members|members_profiles)/', $sql))
    {
        // do if statement stuff here...
    }
    

    注意() 代替[]\s+ 代替空格。因为 SQL 对任意数量的 nay 空格都有效,并且\s+ 与它们都匹配。 \s 后面的+ 表示必须至少有一个空格,但也可以更多。 (?i) 表示将检查所有后续字符不区分大小写,(?-i) 再次打开区分大小写。由于 SQL 命令不区分大小写。

    (abc|def) 匹配 abcdef
    [abc|def] 匹配 abc|def

    要试用一个正则表达式,你可以使用http://rubular.com/,它说它是用 ruby​​ 编写的,用于在 ruby​​ 中测试正则表达式,但有效的正则表达式应该独立于语言,所以它可以用来测试常见的正则表达式,这很有效其他语言也一样。

    【讨论】:

      【解决方案3】:

      正则表达式

      [ab|cd]
      

      不匹配 abcd 但匹配以下单个 (!) 字符之一:ab|c 或 @ 987654329@.

      你需要的是一个组而不是一个字符类:

      (ab|cd)
      

      匹配 abcd

      更多关于字符类的信息:http://www.regular-expressions.info/charclass.html

      【讨论】:

        【解决方案4】:

        这是正确的

        if (
            preg_match('/INSERT\sINTO\s(members|members_profiles)/', $sql) ||
            preg_match('/UPDATE\s(members|members_profiles)/', $sql) ||
            preg_match('/DELETE\sFROM\s(members|members_profiles)/', $sql))
        {
            // do if statement stuff here...
        }
        

        LE: 使用空格特殊字符更改空格转义

        【讨论】:

        • 不需要转义空白。
        • 您能解释一下preg-match 调用中反斜杠字符的作用吗?
        • Martin,反斜杠用于转义字符 - 在正则表达式中具有特殊含义的字符,以获得字面值,或者是字面值以赋予特殊含义的字符。 (例如,使用\\(\| 获取文字(| 字符,而\w 给出“单词字符”的特殊含义等)在这种情况下,不需要反斜杠。跨度>
        • 安全总比后悔好。我总是转义特殊字符,包括空格。
        • 在教别人的时候最好是正确的!空格字符不是特殊字符。
        【解决方案5】:

        除了其他用户已经报告的错误之外,如果您需要检测查询何时尝试更改表 membersmembers_profiles,则您的正则表达式过于严格。

        我不会使用这种方法,但如果你真的需要这样做,那么考虑一下

        • 数据库引擎允许 cmets。如果数据库引擎是MySQL,我可以写INSERT INTO /* little trick */ members …,或者INSERT /* into */ INTO /* table */ members …
        • 数据库引擎允许使用任意数量的空格或换行符。

        【讨论】:

        • 仅供内部查询使用;来自应用程序模型的查询,而不是用户生成/用户提交的查询。
        猜你喜欢
        • 1970-01-01
        • 2019-10-09
        • 1970-01-01
        • 1970-01-01
        • 2019-08-05
        • 1970-01-01
        • 2019-12-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多