我试图将文本分成逗号分隔的组,除非逗号在双引号或单引号中,或在括号中。
。
a,b=456
应该找到a
和b=345
,a='123,456',b
应该找到a='123,456'
和b
a=x(1,2,3),b,c
应该找到a=x(1,2,3)
、b
和c
我试过str_getcsv
和一些preg_split
,但我似乎不能得到正确的模式。
使用以下代码
function test($n, $a,$b) {
echo "Test $n";
if ( $a===$b ) echo "=<span style='color:green'>CORRECT ************************</span>";
else echo "=<span style='color:red'>WRONG</span>";
echo "<PRE>".print_r($b, true)."</PRE>";
echo "<HR>n";
}
$t= 'lorem ipsum=123,delor='1,456',sit="123,456",amet=xxx(2,3),"consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."';
$want=["lorem ipsum=123","delor='1,456'","sit="123,456"","amet=xxx(2,3)","consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."];
和
echo "WANTED.<PRE style='color:green'>".print_r($want, true)."</PRE><HR>";
//Array
//(
// [0] => lorem ipsum=123
// [1] => delor='1,456'
// [2] => sit="123,456"
// [3] => amet=xxx(2,3)
// [4] => consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
//)
test("1 explode", $want, explode(",", $t));
// Test 1 explode=WRONG
// Array
// (
// [0] => lorem ipsum=123
// [1] => delor='1
// [2] => 456'
// [3] => sit="123
// [4] => 456"
// [5] => amet=xxx(2
// [6] => 3)
// [7] => "consectetur adipiscing elit
// [8] => sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )
test("2 str_getcsv", $want, str_getcsv($t, ",", "'"));
// Test 2 str_getcsv=WRONG
// Array
// (
// [0] => lorem ipsum=123
// [1] => delor='1
// [2] => 456'
// [3] => sit="123
// [4] => 456"
// [5] => amet=xxx(2
// [6] => 3)
// [7] => "consectetur adipiscing elit
// [8] => sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )
test("3 str_getcsv", $want, str_getcsv($t, ",", """));
// Test 2 str_getcsv=WRONG
// Array
// (
// [0] => lorem ipsum=123
// [1] => delor='1
// [2] => 456'
// [3] => sit="123
// [4] => 456"
// [5] => amet=xxx(2
// [6] => 3)
// [7] => "consectetur adipiscing elit
// [8] => sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )
test("4 preg_split", $want, preg_split("/,/", $t));
// Test 4 preg_split=WRONG
// Array
// (
// [0] => lorem ipsum=123
// [1] => delor='1
// [2] => 456'
// [3] => sit="123
// [4] => 456"
// [5] => amet=xxx(2
// [6] => 3)
// [7] => "consectetur adipiscing elit
// [8] => sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."
// )
我已经失去了大量的时间搜索和尝试不同的模式-我敢肯定我会写一个字符串解析器比这更快-但也许-有人能给我一个很好的模式,通过这个工作?
我在https://onlinephp.io/c/3f4d3上放了一个示例测试来运行这个代码
感谢我建议使用
preg_match_all('~(?:'[^']*'|"[^"]*"|(((?:[^()]++|(?1))*))|[^'",])+~', $text, $matches)
或者,如果在加引号的子字符串中可以有转义序列:
preg_match_all('~(?:'[^'\\]*(?:\\.[^'\\]*)*'|"[^"\\]*(?:\\.[^"\\]*)*"|(((?:[^()]++|(?1))*))|[^'",])+~s', $text, $matches)
参见regex演示。
细节:
(?:
-非捕获组的开始(在这里充当容器):'[^'\\]*(?:\\.[^'\\]*)*'|
-支持转义序列的单引号之间的字符串,或"[^"\\]*(?:\\.[^"\\]*)*"|
-支持转义序列的双引号之间的字符串,或(((?:[^()]++|(?1))*))|
-两个成对嵌套括号之间的字符串[^'",]
-'
,"
和,
以外的字符
)+
-一个或多个序列。