0

我不确定是否应该将 preg_match、preg_match_all 或 preg_split 与 delim 捕获一起使用。我也不确定正确的正则表达式。

鉴于以下情况:

$string = " ok 'that\\'s cool' \"yeah that's \\\"cool\\\"\"";

我想得到一个包含以下元素的数组:

[0] = "ok"
[1] = "that\'s"
[2] = "yeah that's \"cool\""
4

3 回答 3

1

您不能使用正则表达式来执行此操作,因为您正在尝试解析非上下文无关语法。编写解析器。

大纲:

  • 一个字一个字地读,如果你看到了\就记住了。
  • 如果您看到 a"'检查前一个字符是否为\. 你现在有了你的定界条件。
  • 以这种方式记录所有令牌

您想要的结果集似乎修剪了空格,您还丢失了几个\s,也许这是一个错误,但它可能很重要。

我希望:

[0] = " ok " // <-- spaces here
[1] = "that\\'s cool"
[2] = " \"yeah that's \\\"cool\\\"\"" // leading space here, and \" remains
于 2013-07-26T16:14:46.087 回答
1

实际上,您可能会惊讶地发现您可以在正则表达式中执行此操作:

preg_match_all("((?|\"((?:\\\\.|[^\"])+)\"|'((?:\\\\.|[^'])+)'|(\w+)))",$string,$m);

所需的结果数组将位于$m[1].

于 2013-07-26T16:25:09.007 回答
0

您可以使用正则表达式来做到这一点:

$pattern = <<<'LOD'
~
(?J) 

# Definitions #
(?(DEFINE)
  (?<ens> (?> \\{2} )+ ) # even number of backslashes

  (?<sqc> (?> [^\s'\\]++  | \s++ (?!'|$)    | \g<ens> | \\ '?+    )+ ) # single quotes content
  (?<dqc> (?> [^\s"\\]++  | \s++ (?!"|$)    | \g<ens> | \\ "?+    )+ ) # double quotes content
  (?<con> (?> [^\s"'\\]++ | \s++ (?!["']|$) | \g<ens> | \\ ["']?+ )+ ) # content
)
# Pattern #
    \s*+ (?<res> \g<con>)
| ' \s*+ (?<res> \g<sqc>) \s*+ '?+
| " \s*+ (?<res> \g<dqc>) \s*+ "?+ 
~x
LOD;
$subject = " ok 'that\\'s cool' \"yeah that's \\\"cool\\\"\"";

preg_match_all($pattern, $subject, $matches, PREG_SET_ORDER);
foreach($matches as $match) {
    var_dump($match['res']);
}

我选择在所有结果中修剪空格,然后" abcd "给出abcd. 这种模式允许在任何你想要的任何地方使用所有你想要的反斜杠。如果带引号的字符串在字符串的末尾没有关闭,则字符串的结尾被认为是右引号(这就是我将右引号设为可选的原因)。所以,abcd " ef'gh会给你abcdef'gh

于 2013-07-26T21:09:30.380 回答