我找到了这个问题的几个部分答案,但没有一个能满足我的所有需求......
我正在尝试解析用户生成的字符串,就好像它是一系列php函数参数来确定参数的数量:
此字符串:
$arg1,$arg2='ABC,DEF',$arg3="GHI\",JKL",$arg4=array(1,'2)',"3\"),")
将作为函数的参数插入:
function my_function( [insert string here] ){ ... }
我需要解析逗号上的字符串,考虑单引号和双引号,括号以及转义的引号和括号来创建数组:
array(4) {
[0] => $arg1
[1] => $arg2='ABC,DEF'
[2] => $arg3="GHI\",JKL"
[3] => $arg4=array(1,'2)',"3\"),")
}
任何有关正则表达式或解析器函数的帮助都是值得赞赏的!
答案 0 :(得分:1)
使用传统的csv工具无法解决此问题,因为有多个字符能够保护字符串的某些部分。
使用preg_split
是可能的,但会导致非常复杂和低效的模式。所以最好的方法是使用preg_match_all
。但是有几个问题需要解决:
对于第一点,您可以定义子模式来描述每种情况:引用的部分,括号之间的部分,以及能够匹配完整参数的更一般的子模式,以及在需要时使用前两个子模式。
请注意,括号子模式也需要引用通用子模式,因为它可以包含任何内容(以及逗号)。
可以使用\G
锚来解决第二点,确保所有匹配都是连续的。但是你需要确保已经达到了字符串的结尾。为此,您可以在主模式的末尾添加一个可选的空捕获组,仅当字符串\z
的结尾的锚点成功时才会创建。
$subject = <<<'EOD'
$arg1,$arg2='ABC,DEF',$arg3="GHI\",JKL",$arg4=array(1,'2)',"3\"),")
EOD;
$pattern = <<<'EOD'
~
# named groups definitions
(?(DEFINE) # this definition group allows to define the subpatterns you want
# without matching anything
(?<quotes>
' [^'\\]*+ (?s:\\.[^'\\]*)*+ ' | " [^"\\]*+ (?s:\\.[^"\\]*)*+ "
)
(?<brackets> \( \g<content> (?: ,+ \g<content> )*+ \) )
(?<content> [^,'"()]*+ # ' # (<-- comment for SO syntax highlighting)
(?:
(?: \g<brackets> | \g<quotes> )
[^,'"()]* # ' #
)*+
)
)
# the main pattern
(?: # two possible beginings
\G(?!\A) , # a comma contiguous to a previous match
| # OR
\A # the start of the string
)
(?<param> \g<content> )
(?: \z (?<check>) )? # create an item "check" when the end is reached
~x
EOD;
$result = false;
if ( preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER) &&
isset(end($matches)['check']) )
$result = array_map(function ($i) { return $i['param']; }, $matches);
else
echo 'bad format' . PHP_EOL;
var_dump($result);
答案 1 :(得分:0)
您可以将参数字符串拆分为,$
,然后将$
追加回数组值:
$args_array = explode(',$', $arg_str);
foreach($args_array as $key => $arg_raw) {
$args_array[$key] = '$'.ltrim($arg_raw, '$');
}
print_r($args_array);
输出:
(
[0] => $arg1
[1] => $arg2='ABC,DEF'
[2] => $arg3="GHI\",JKL"
[3] => $arg4=array(1,'2)',"3\"),")
)
答案 2 :(得分:0)
如果您想使用正则表达式,可以使用以下内容:
(.+?)(?:,(?=\$)|$)
<强> Working demo 强>
Php代码:
$re = '/(.+?)(?:,(?=\$)|$)/';
$str = "\$arg1,\$arg2='ABC,DEF',\$arg3=\"GHI\",JKL\",\$arg4=array(1,'2)',\"3\"),\")\n";
preg_match_all($re, $str, $matches);
匹配信息:
MATCH 1
1. [0-5] `$arg1`
MATCH 2
1. [6-21] `$arg2='ABC,DEF'`
MATCH 3
1. [22-39] `$arg3="GHI\",JKL"`
MATCH 4
1. [40-67] `$arg4=array(1,'2)',"3\"),")`