PHP 正则表达式:在 2 个括号之间找到许多单词


PHP Regex: find many words between 2 parentheses

我正在尝试解析一个"插入"MySQL数据库查询,它可能看起来像这样:

insert into tablename (field1,   field2, field3) values ('te''s ,, t', 3, "OO,'"P")

假设:查询始终是"合法"/没有错误的。

规则:

  1. 我想在tablename之后抓取第一个参数之间的所有字段名称

2-字段名可以包含[a-z0-9_],它总是跟着空格或逗号[, ]。可以有很多空格,也可以只有一个或零个空格。

由于某些原因,它不起作用:我问"在第一个括号后找到所有 1-100 个字符的单词,后面可能有也可能不跟一个或多个逗号或空格:

preg_match_all( 'tablename '(('w{1,100}(?:[, ])*)+') values/si', $matches, $allfields );

我尝试在 PHP 中运行 preg_match_all(),它只返回最后一个字段。我错过了什么?

首先:顺便说一句,尝试使用简单/朴素的文本方法解析像SQL这样复杂的语言是一个坏主意。

关于您的特定问题,您的模式不起作用,因为您正在尝试从重复的捕获组中提取数据。重复捕获组时,上一个捕获始终被下一个捕获覆盖,依此类推。

执行此操作的模式更为复杂。这是一个经典的问题:如何在两个子字符串之间提取几个东西(重复的东西)?

执行此操作

的方法需要使用与上一个结果末尾的位置匹配的'G锚点。(注意:在开始时,由于没有先前的结果,因此'G锚点与字符串的开头匹配。若要避免这种情况,必须使用负的预(?!'A)以确保字符串的开头将失败。

(?:'G(?!'A)'s*,|insert's+into's+tablename's*'()'s*'K'w+

图案详情:

(?:             # non capturing group with the two possible beginings
    'G(?!'A) 's* , # contigous to the previous match, spaces, comma
  |                # OR
    insert's+into's+tablename's*'( # the branch for the first result
)
's*                        
'K    # discard all characters on the left from whole match result
'w+   # the field name

演示

当到达最后一个字段时,连续性将被破坏,因为只有一个右括号而不是逗号。所以'G不会再成功了。

你需要使用正则表达式吗?

为此,我会使用 PHP 自己的字符串函数。

找到左括号和结束括号的位置:

$start = strpos( $sqlQuery, "(" )
$stop = strpos( $sqlQuery, ")" )

然后使用以下命令提取字段名称部分:

$names = substr($sqlQuery, $start, $stop - $start )

然后,您可以分解结果以获取每个字段名称的数组:

$nameParts = explode($names, ",")