Php 匹配2个或多个嵌套可选项的正则表达式

Php 匹配2个或多个嵌套可选项的正则表达式,php,regex,preg-match-all,Php,Regex,Preg Match All,我想使用preg_match_all解析此字符串: $str = "form.input|type() form.input|type('text') form.input|type('text', {'width': '100px', 'height': '50px'}) form.input|type('image', {'path': '/path/to/image'})"; preg_match_all('/form\.input\|ty

我想使用preg_match_all解析此字符串:

$str = "form.input|type()
        form.input|type('text')
        form.input|type('text', {'width': '100px', 'height': '50px'})
        form.input|type('image', {'path': '/path/to/image'})";

preg_match_all('/form\.input\|type\((?:(.*))?\)/', $str, $matches);
预期产出:

 [0] => Array
    (
        [0] => form.input|type()
        [1] => form.input|type('text')
        [2] => form.input|type('image', {'path': '/path/to/image'})
        [3] => form.input|type('text', {'width': '100px', 'height': '50px'})
    )

 [1] => Array
    (
        [0] => 
        [1] => text
        [2] => image
        [3] => text
    )

[2] => Array
    (
        [0] => 
        [1] => 
        [2] => {'path': '/path/to/image'}
        [3] => {'width': '100px', 'height': '50px'}
    )
实际产出:

Array
(
    [0] => Array
        (
            [0] => form.input|type()
            [1] => form.input|type('text')
            [2] => form.input|type('image', {'path': '/path/to/image'})
            [3] => form.input|type('text', {'width': '100px', 'height': '50px'})
        )

    [1] => Array
        (
            [0] => 
            [1] => 'text'
            [2] => 'image', {'path': '/path/to/image'}
            [3] => 'text', {'width': '100px', 'height': '50px'}
        )

)
此模式可以分析以下情况:

form.input|type()
form.input|type('text')
我试图通过以下模式匹配:

/form\.input\|type\((?:(.*)(?:,(.*))?)?\)/
但由于未捕获子组,它无法匹配模式

我使用非捕获组
(?:(.*)?
进行可选匹配,但它只能在没有使用第一个模式的子非捕获组时进行匹配


在本例中,我试图搜索匹配,但找不到正确答案。

您可以使用正则表达式和
explode()的组合:

看。

补遗 要去掉引号,可以使用

<?php

$strings = ["form.input|type()",
                        "form.input|type('text')",
                        "form.input|type('text', {'width': '100px', 'height': '50px'})", 
                        "form.input|type('image', {'path': '/path/to/image'})']",
                        "form.input|type(\"image\", {'path': '/path/to/image2'})']"];


$regex = '~\(([^()]+)\)~';
$key_value = '~^([\'"])(.+?)\1(?:, )?(.*)~';

foreach ($strings as $string) {
    if (preg_match($regex, $string, $match)) {
        if (preg_match($key_value, $match[1], $inner)) {
            $key = $inner[2];
            $value = $inner[3];
            echo "Key = $key, Value = $value\n";
        }
    }
}
?>
这个


下面是我建议的处理单引号和双引号的模式:()

模式说明:

form\.input\|type\(  // Literally match the static/known leading characters
['"]?                // optionally match a single or double quote
([a-z]*)             // greedily capture zero or more lowercase letters
['"]?                // optionally match a single or double quote
(?:, )?              // optionally match a comma followed by a space
([^)]*)              // greedily capture zero or more non-closing parenthesis characters
实际上,通过使用“零或一”(
)或“零或多”(
*
)量词,字符串可以具有空或非空的括号成分,并确保在输出数组中传递两个预期捕获组

PHP代码:()

输出:

Array
(
    [0] => Array
        (
            [0] => 
            [1] => text
            [2] => text
            [3] => image
        )

    [1] => Array
        (
            [0] => 
            [1] => 
            [2] => {'width': '100px', 'height': '50px'}
            [3] => {'path': '/path/to/image'}
        )

)

您期望的输出是什么?您的模式匹配上述所有情况:甚至@Jan I用预期的输出编辑了问题。此模式将type()中的所有内容作为一个字符串进行匹配。但是我想把它们分为两部分来匹配:字符串类型和json选项。从您的示例来看,这已经足够了。+/
@miknik请您在示例中应用它好吗/form\.input\| type((?:(.*))/@semsem您的问题是“我想使用preg_match解析这个字符串”,这对我来说有点不清楚。您是否使用
preg\u match\u all()
从每行中提取值?或者这实际上是四个单独的示例字符串,您希望对所有四个字符串调用
preg\u match()
?请将您的php实现添加到问题中,以澄清实际任务?是否希望每次返回2个捕获组?即使一个或两个捕获组都为空?这些都是您的问题中必须包含的关键细节。谢谢@Jan,有没有比替换匹配输出字符串中的单引号和双引号更好的方法“文本”和“文本”请不要只发布代码答案——永远不要。它们也许能解决这个问题,但价值很低,对未来读者的教育作用甚微。把它想象成一个有成千上万学生的教室。请更新您的答案。@semsem此答案不正确,对吗?因为它不会从第一个示例字符串返回任何匹配项。问题中没有php代码,因此我们不知道您是否希望每次返回2个匹配项(可能为空),或者是否将不匹配项作为第一个示例字符串的有效结果处理。(
form.input | type()
)请澄清您的4个示例输入的预期输出数组。@此答案不准确。很抱歉,我将用php代码编辑问题以澄清。
Key = text, Value = 
Key = text, Value = {'width': '100px', 'height': '50px'}
Key = image, Value = {'path': '/path/to/image'}
Key = image, Value = {'path': '/path/to/image2'}
preg_match_all('/((?<=\(\')\w+)|({.*})/', $input, $matches, PREG_PATTERN_ORDER, 0);

print_r($matches);
Array
(
[0] => Array
(
[0] => text
[1] => {'width': '100px', 'height': '50px'}
)
/form\.input\|type\(['"]?([a-z]*)['"]?(?:, )?([^)]*)/
form\.input\|type\(  // Literally match the static/known leading characters
['"]?                // optionally match a single or double quote
([a-z]*)             // greedily capture zero or more lowercase letters
['"]?                // optionally match a single or double quote
(?:, )?              // optionally match a comma followed by a space
([^)]*)              // greedily capture zero or more non-closing parenthesis characters
$str = "form.input|type()   
        form.input|type('text')
        form.input|type(\"text\", {'width': '100px', 'height': '50px'})
        form.input|type('image', {'path': '/path/to/image'})";

print_r(preg_match_all("/form\.input\|type\(['\"]?([a-z]*)['\"]?(?:, )?([^)]*)/",$str,$out)?array_slice($out,1):'fail');
Array
(
    [0] => Array
        (
            [0] => 
            [1] => text
            [2] => text
            [3] => image
        )

    [1] => Array
        (
            [0] => 
            [1] => 
            [2] => {'width': '100px', 'height': '50px'}
            [3] => {'path': '/path/to/image'}
        )

)