我正在处理模板类,在尝试从字符串参数列表中解析出引用字符串列表时遇到问题。以字符串为例:
$string = 'VAR_SELECTED, \'Hello m\'lady\', "null"';
我遇到了一个提取字符串“Hello m'lady”和“null”的正则表达式的问题。我最接近的是
$string = 'VAR_SELECTED, \'Hello m\'lady\', "null", \'TE\'ST\'';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);
哪个输出:
Array
(
[0] => Array
(
[0] => VAR_SELECTED,
[1] => 'Hello m'lady',
[2] => "null",
[3] => 'TE'ST'
)
)
然而更复杂的情况是:
$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"';
preg_match_all('/(?:[^\']|\\\\.)+|(?:[^"]|\\\\.)+/', $string, $matches);
print_r($matches);
输出:
Array
(
[0] => Array
(
[0] => VAR_SELECTED,
[1] => 'Hello
[2] => "Father"
[3] => ',
[4] => "Hello
[5] => 'Luke'
[6] => "
)
)
任何人都可以帮我解决这个问题吗?多个正则表达式是前进的方向吗?
编辑也许用占位符替换字符串中的逗号会更容易,然后用爆炸拆分字符串?
编辑2 刚想到一个简单的不安全选项(我不打算使用),但会产生E_NOTICE错误。
$string = 'return array(VAR_SELECTED, \'Hello , "Father"\', "Hello \'Luke\'4");';
$string = eval($string);
print_r($string);
答案 0 :(得分:3)
试试这个:
/(?<=^|[\s,])(?:(['"]).*?\1|[^\s,'"]+)(?=[\s,]|$)/
或者,作为PHP单引号字符串文字:
'/(?<=^|[\s,])(?:([\'"]).*?\1|[^\s,\'"]+)(?=[\s,]|$)/'
正则表达式产生了预期的结果,但我认为你会出现这种错误。通常,如果带引号的字符串需要包含文字引号字符,则使用反斜杠或其他引号对引号进行转义。你没有这样做,所以我不得不使用基于外观的脆弱黑客。你确定数据不应该是这样的吗?
$string = 'VAR_SELECTED, \'Hello m\\'lady\', "null"';
$string = 'VAR_SELECTED, \'Hello "Father"\', "Hello \\'Luke\\'"';
想一想,PHP是否内置了对CSV数据的支持?
答案 1 :(得分:1)
以下是我将如何做到这一点:
将任务分解为您要采取的组件步骤:
1。)用逗号分解字符串。
For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello m\'lady\'"
[2]=>" "null""
For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>" \'Hello "Father"\'"
[2]=>" "Hello \'Luke\'""
2。)在所有三个上运行修剪以消除任何空白
For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello m\'lady\'"
[2]=>""null""
For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"\'Hello "Father"\'"
[2]=>""Hello \'Luke\'""
3。)运行str_replace(“\”,“”,$ text)去掉斜杠。 (删除space..added只是为了可读性,所以应该是一个裸斜线和一个“空”字符串)
For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello m'lady'"
[2]=>""null""
For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"'Hello "Father"'"
[2]=>""Hello 'Luke'""
4.。)再次运行修剪,仅修剪($ text,“'”“)(删除空格......仅为了可读性而添加)
For 'VAR_SELECTED, \'Hello m\'lady\', "null"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello m'lady"
[2]=>"null"
For 'VAR_SELECTED, \'Hello "Father"\', "Hello \'Luke\'"' this gives me
[0]=>"VAR_SELECTED"
[1]=>"Hello "Father""
[2]=>"Hello 'Luke'"
我没有测试过这个,但逻辑是合理的。测试98%所有正则表达式的快速而肮脏的方法(根据我的经验)是使用http://rubular.com/这是一个很棒的网站。通常,如果它开始扼杀正则表达式,这是我的第一个迹象,我应该更多地解决问题。 (这只是意见〜防火服〜)
答案 2 :(得分:0)
您想在匹配字符串中使用back reference。
preg_match_all('@([\'"]).*[^\\\\]\1@', $string, $matches);
这将开始与“or”的第一个实例匹配,然后匹配以匹配的最长字符串“或”未转义。
Array (
[0] => Array
(
[0] => 'Hello m'lady', "null", 'TE'ST'
)
[1] => Array
(
[0] => '
)