正则表达式匹配2个或更多嵌套的可选术语

时间:2017-12-03 21:02:44

标签: 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\|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\((?:(.*)(?:,(.*))?)?\)/

但由于儿童非捕获组,它无法匹配模式。

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

我尝试在这种情况下搜索匹配,但我找不到正确的答案。

3 个答案:

答案 0 :(得分:1)

您可以使用正则表达式和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'})']"];

$regex = '~\(([^()]+)\)~';

foreach ($strings as $string) {
    if (preg_match($regex, $string, $match)) {
        list($key, $value) = explode(", ", $match[1], 1);
        echo $key, $value . "\n";
    }
}
?>

a demo on ideone.com

<小时/> 这里的想法是在()中查找内容,然后在找到的第一个,上进行拆分/爆炸。如果要将表达式限制为form.input,可以将表达式更改为:

\Qform.input|type\E\(([^()]+)\)

a demo on regex101.com

<小时/>

附录

要删除引号,可以使用

<?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";
        }
    }
}
?>

哪个收益

Key = text, Value = 
Key = text, Value = {'width': '100px', 'height': '50px'}
Key = image, Value = {'path': '/path/to/image'}
Key = image, Value = {'path': '/path/to/image2'}

答案 1 :(得分:1)

以下是我建议处理单引号和双引号的模式:(Pattern Demo

/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

有效地,通过使用“零或一个”(?)或“零或更多”(*)量词,字符串可以具有空的或非空的括号组件并确保两者都是预期的捕获组在输出数组中传递。

PHP代码:(Demo

$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'}
        )

)

答案 2 :(得分:0)

这个

preg_match_all('/((?<=\(\')\w+)|({.*})/', $input, $matches, PREG_PATTERN_ORDER, 0);

print_r($matches);

将返回此:

Array
(
[0] => Array
(
[0] => text
[1] => {'width': '100px', 'height': '50px'}
)