我试图解析"插入" MySQL数据库查询可能如下所示:
insert into tablename (field1, field2, field3) values ('te\'s ,, t', 3, "OO,\"P")
假设:查询始终是合法的' /没有错。
规则:
tablename
2-字段名称可以包含[a-z0-9_]
,始终后跟空格或逗号[, ]
。可能有很多空格或只有一个或零个。
由于某些原因,它不起作用:我要求"在第一个括号后找到1-100个字符的所有单词,可能会或不会出现一个或多个昏迷或空格:
preg_match_all( 'tablename \((\w{1,100}(?:[, ])*)+\) values/si', $matches, $allfields );
我尝试在PHP中运行preg_match_all()并返回 last 字段。我错过了什么?
答案 0 :(得分:2)
首先:顺便说一句,尝试使用简单/朴素的文本方法解析像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
将不再成功。
答案 1 :(得分:0)
您需要使用正则表达式吗?
我会使用PHP自己的String函数。
找到开始和结束括号的位置:
$start = strpos( $sqlQuery, "(" )
$stop = strpos( $sqlQuery, ")" )
然后使用以下内容提取字段名称部分:
$names = substr($sqlQuery, $start, $stop - $start )
然后,您可以展开结果以获取每个字段名称的数组:
$nameParts = explode($names, ",")