尝试从PHP获取所有匹配项preg_match_all

时间:2017-09-19 23:52:39

标签: php regex preg-match-all

我正在尝试匹配引用字符串列表并获取每个引用的子字符串。 PHP的preg_match_all验证了引用字符串的列表,但返回的“$ matches”不包含所有引用的子字符串 - 通常它只返回第一个和最后一个。

我尝试将名称(?P<name>)分配给表达式的组件,但这似乎只会导致结果重复,而且我仍然没有收到所有引用的子字符串。

使用DEFINE为组件创建子例程并没有改善结果。

以下是我想要匹配的输入示例。

   'abcd','efgh"ij','list,543','Brown fox.','left(paren','right)paren'

下面是我正在使用的表达式。请注意,字符串仅用单引号引用。

   /(?x)^   (\x27[^\x27]*\x27)   (,(\x27[^\x27]*\x27))*    $/

preg_match_all的调用如下:

$pregex = '/(?x)^   (\x27[^\x27]*\x27)   (,(\x27[^\x27]*\x27))*    $/';
echo 'Match result: '.preg_match_all($pregex, $text_list, $matches, PREG_PATTERN_ORDER)."\n";

执行后,$ matches包含:

Array
(
    [0] => Array
        (
            [0] => 'abcd','efgh"ij','list,543','Brownfox.','left(paren','right)paren'
        )

    [1] => Array
        (
            [0] => 'abcd'
        )

    [2] => Array
        (
            [0] => ,'right)paren'
        )

    [3] => Array
        (
            [0] => 'right)paren'
        )

)

......我注意到它的字符串是“布朗狐狸”。改为“Brownfox。”,这是一个问题,它没有列出所有引用的子串。

我希望看到的是(注意在返回的子串的开头没有逗号,但是如果它们必须在那里,那么就是这样):

Array
(
    [0] => Array
        (
            [0] => 'abcd','efgh"ij','list,543','Brownfox.','left(paren','right)paren'
        )

    [1] => Array
        (
            [0] => 'abcd'
        )

    [2] => Array
        (
            [0] => 'efgh”ij'
        )

    [3] => Array
        (
            [0] => 'list,543'
        )

    [3] => Array
        (
            [0] => 'Brown fox.'
        )

    [3] => Array
        (
            [0] => 'left(paren'
        )

    [3] => Array
        (
            [0] => 'right)paren'
        )

)

我想我的问题是:

  1. 是否可以使用preg_match_all完成我想要的任务?
  2. 如果有可能,那么我做错了什么或者我做错了什么 理解?
  3. 如果可能的话,我该如何完成 需要解析?
  4. 谢谢!

1 个答案:

答案 0 :(得分:-1)

非常感谢Crayon Violent的帮助!他的表达解决了我的问题。

我选择了他提供的正则表达式解决方案,因为当子字符串包含一个或多个逗号(如'efgh"ij','list,543','Brown fox'中)时,"list,543"子字符串中的逗号会通过爆炸抛出解析。

我原来的正则表达式在验证输入方面做得很好,但它没有提供子串数组。正则表达式Crayon Violent提供DOES提供子串数组,但不验证输入,所以我的解决方案是使用两者,如:

$token_count = 0;

// Trim leading and trailing blanks from the input.
$trimmed_input_text = trim($text_input);

// Validate the input using preg_match
$pregex_validate = '/(?x)^ [ ]*  \(   [ ]*   (\x27[^\x27]*\x27)  (   [ ]*   ,  [ ]*   (\x27[^\x27]*\x27))*   [ ]*   \)  [ ]*   $/';
if (preg_match($pregex_validate, $trimmed_input_text)) {
   // Use preg_match_all to get the substrings in an array
   $pregex_parse = "~'([^']+)'~";
   $token_count = preg_match_all($pregex_parse, $trimmed_input_text, $matches);
}

结果$matches产生:

Array
(
    [0] => Array
        (
            [0] => 'abcd'
            [1] => 'efgh"ij'
            [2] => 'list,543'
            [3] => 'Brown fox.'
            [4] => 'left(paren'
            [5] => 'right)paren'
        )

    [1] => Array
        (
            [0] => abcd
            [1] => efgh"ij
            [2] => list,543
            [3] => Brown fox.
            [4] => left(paren
            [5] => right)paren
        )

)

......这正是我想要的!

再次,非常感谢Crayon Violent的帮助!

约翰