【问题标题】:Trying to get all matches from PHP preg_match_all试图从 PHP preg_match_all 获取所有匹配项
【发布时间】:2017-09-19 23:52:39
【问题描述】:

我正在尝试匹配带引号的字符串列表并获取每个带引号的子字符串。 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'
        )

)

...我注意到它是字符串“Brown fox”。更改为“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. 如果有可能,那么我该如何完成 需要解析吗?

谢谢!

【问题讨论】:

  • $string = explode(',',$string); $string = array_map('trim',$string,array_fill(0,count($string),"'"));
  • 或者如果你想坚持使用正则表达式.. preg_match_all("~'([^']+)'~",$string,$matches);print_r($matches);
  • 谢谢!我会试一试!我不确定“~”是做什么的,但我会查一下。
  • 它是模式分隔符。您在模式中使用了/。但是你基本上可以使用任何东西。我个人赞成~,因为原因
  • 没关系 - "~" 是表达式的分隔符!

标签: php regex preg-match-all


【解决方案1】:

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

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

我拥有的原始正则表达式在验证输入方面做得很好,但它没有提供子字符串数组。正则表达式 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 的帮助!

约翰

【讨论】:

  • 使用正则表达式只是浪费时间:str_getcsv(trim($str), ',', "'") 在一行中做同样的事情。
  • 太棒了!谢谢!它正确处理了一个嵌入逗号的字符串!谢谢!在 PHP 近 20 年的时间里,str_getcsv 是我从未遇到过的一个函数。
猜你喜欢
  • 2012-07-05
  • 2016-04-03
  • 1970-01-01
  • 2015-03-23
  • 1970-01-01
  • 2019-01-30
  • 2011-08-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多