Php 获取所选列的正则表达式

Php 获取所选列的正则表达式,php,mysql,regex,Php,Mysql,Regex,我必须从MYSQL SELECT中提取列名,我希望使用正则表达式来实现这一点。 这是一个简单的选择,类似于: 选择第1列、第2列。。。从桌子上 我必须涵盖所有情况,包括我们的无别名、前面有无表格、有无引用字符: SELECT column, column as foo, table.column, table.column as foo, `column`, `column` as foo, `table`.`column`, `table`.`column` as foo

我必须从MYSQL SELECT中提取列名,我希望使用正则表达式来实现这一点。 这是一个简单的选择,类似于: 选择第1列、第2列。。。从桌子上

我必须涵盖所有情况,包括我们的无别名、前面有无表格、有无引用字符:

SELECT column, column as foo, table.column, table.column as foo, 
       `column`, `column` as foo, `table`.`column`, `table`.`column` as foo
       .....
目前,我已经能够计算出这个正则表达式:\w+\sas?I,但它与前缀列相比并不好。 有什么帮助吗

顺便问一下,Regex擅长这个任务吗

编辑 谢谢你的回答! 您发布的模式对整个查询都有效,实际上我已经在处理每一列:

$fields = Frameworkmethod::getSelectFields($query);
$columns = explode(',' , $fields);
foreach($columns as $column)
{
     //do Regex work to "clean up" the single field and get the "standard" one (not the alias)
     //`#__tracktime_projects`.`pr_name` AS `project_name` should return pr_name
}
如上所述,我总是需要字段名,而不是别名。 对不起,之前没有指出

我使用了PHP:

$query = 'SELECT column1, column2 as foo, table.column3, table.column4 as foo, 
       `column5`, `column6` as foo, `table`.`column7`, `table`.`column8` as foo
       FROM table';

$query = preg_replace('/^SELECT(.*?)FROM.*$/s', '$1', $query); // To remove the "SELECT" and "FROM table..." parts

preg_match_all('/(?:
    (?:`?\w+`?\.)? (?:`)?(\w+)(?:`)? (?:\s*as\s*\w+)?\s*
#   ^--TableName-^ ^---ColumnName--^ ^----AsFoo-----^
)+/x',$query, $m);

print_r($m[1]);
输出:

Array
(
    [0] => column1
    [1] => column2
    [2] => column3
    [3] => column4
    [4] => column5
    [5] => column6
    [6] => column7
    [7] => column8
)
Array
(
    [0] => column1
    [1] => column2
    [2] => column3
    [3] => column4
    [4] => column5
    [5] => column6
    [6] => column7
    [7] => column8
    [8] => pr_name
    [9] => #wut
)
现场演示:

更新:因为您使用了一些不寻常但有效的SQL表名,例如:uu tracktime_projects,所以它把正则表达式搞乱了。为了解决这个问题,我添加了一个变量,其中包含我们期望的字符,我还添加了I修饰符,使匹配无大小写:

$query = 'SELECT column1, column2 as foo, table.column3, table.column4 as foo, 
       `column5`, `column6` as foo, `table`.`column7`, `table`.`column8` as foo, `#__tracktime_projects`.`pr_name` AS project_name, `#wut`
       FROM table';


$query = preg_replace('/^SELECT(.*?)FROM.*$/s', '$1', $query); // To remove the "SELECT" and "FROM table..." parts

$allowed = '\w#'; // Adjust this to the names that you expect.

preg_match_all('/(?:
    (?:`?['.$allowed.']++`?\.)?
#   ^--------TableName--------^

    (?:`)?(['.$allowed.']++)(?:`)?
#   ^----------ColumnName--------^

    (?:\s*as\s*['.$allowed.']++)?\s*
#   ^-------------AsFoo------------^
)+
/xi',$query, $m);

print_r($m[1]);
输出:

Array
(
    [0] => column1
    [1] => column2
    [2] => column3
    [3] => column4
    [4] => column5
    [5] => column6
    [6] => column7
    [7] => column8
)
Array
(
    [0] => column1
    [1] => column2
    [2] => column3
    [3] => column4
    [4] => column5
    [5] => column6
    [6] => column7
    [7] => column8
    [8] => pr_name
    [9] => #wut
)

LealDemo:

< P>如果使用PHP,我相信其他语言也支持这一点,你可以考虑。从文档中:

<?php
  $select = $DB->query('SELECT COUNT(*) FROM fruit');
  $meta = $select->getColumnMeta(0);
  var_dump($meta);
?>
我利用并调整了它以适应这一目的

因此,一个从*SQL查询中捕获列名的防弹正则表达式:

在线演示说明:

使用preg_match_all和单个正则表达式的PHP代码,用/x修饰符注释:

preg_match_all('/(?:SELECT\s++(?=(?:[\#\w,`.]++\s++)+) # start matching on SELECT
                |              # or
                (?!^)\G        # resume from last match position 
                \s*+,\s*+      # delimited by a comma 
                (?:`?+\s*+     # optional prefix table with optional backtick
                    [\#\w]++   # table name
                    \s*+`?+    # optional backtick
                    \s*+\.\s*+ # dot separator
                )?+ # optional prefix table end group

                `?+\s*+ # optional backtick

            ) # initial match or subsequent match

            (\w++)    # capturing group
            `?+         # optional backtick


            (?:\s++as\s++[^,\s]++)?+ # optional alias

            /ix', $query, $matches);
实时代码:

注意:“希望是防弹的”是针对有效的SQL

使用explode的PHP代码

$columns = explode(',', $fields);

foreach($columns as $column)
{
    $regex='/([\w]++)`?+(?:\s++as\s++[^,\s]++)?+\s*+(?:FROM\s*+|$)/i';

    preg_match($regex, $column, $match);

    print $match[1]; // field stored in $match[1]
}

带有示例提取的实时代码:

这是通用解决方案:

((select|,)\s+((((`)?\w+\6?\.)?(`)?\w+\7?)(\s+as\s+(`)?\w+\9?)?\s*))+from\s
组$3包含可能带有表和别名装饰的列

您可以使用非捕获组-?。。。对于表达的某些部分。在这种情况下,更改反向参考号


使用单行运行它并忽略大小写标志。也许您应该将标识符规范\w+更改为更具体的[a-zA-Z]\w*例如。

这是一个老问题,但我有同样的问题,无法使用@CS解决ᵠ 正则表达式。 我创建了另一个正则表达式,以便在更大范围的列(包括计算字段)上执行此任务

preg_match_all('/(?<=^SELECT |, |\) )([a-z]+\.)?([a-z]+ )?(as )?([a-z]+)(?= ?,|$)/im');

如果将用于复杂的查询,我建议使用我创建的完整函数:

我迟到了,但大多数函数对于我和特定于PHP的PHP来说太复杂了,我猜这就是您想要的,但很多人可能不这么认为。 我用的是PCRE口味的regex:

([\w`]+)(?=\s*,|\s+from\s+)
这将匹配字母数字和反勾号[\w`]+字符,这些字符后面紧跟逗号或空格、逗号或空格以及关键字“from”

后者是通过积极的前瞻来实现的

(?=<expression>)
检查前面的标记[\w`]+后面是否有

\s*,       # whitespace (0 or more) and comma
或|

然后,您可以在任何语言风格中使用case标志来忽略case


编辑:还应注意,这与别名匹配,而不是与原始列名匹配。

Regex是否擅长这项任务,这完全取决于您正在使用的编程语言!指定您正在使用的语言/工具,以便我们可以帮助您。该工具似乎只报告最后一次捕获。在您的验证器中,仅使用“选择”、\s*?\w+\4?\。\w+\5?\s+as\s+`?\w+\7???\s*,但使用isg选项。不是很好。请看regex101.com/r/rL1bE2。你认为这个结果正确吗?它应该列出所有的“a”、“b”和“c”。这就是为什么它没有列出我的正则表达式中的所有列的原因。让我们在上继续讨论,以避免注释空间混乱,也请删除此处的注释这很好,但是我需要字段名而不是别名抱歉,我刚刚更新了questiontesting vs此字符串提取别名而不是列名:
\s*,       # whitespace (0 or more) and comma
\s+from\s+ # the keyword 'from', surrounded by >=1 whitespace characters