使用PHP正则表达式命名捕获的数组

时间:2018-03-23 13:09:49

标签: php regex preg-match

如果命名捕获多次匹配,是否可以检索所有匹配?

实施例

<?php

$string = 'TextToMatch [some][random][tags] SomeMoreMatches';
$pattern = "!(TextToMatch )(?P<tags>\[.+?\])+( SomeMoreMatches)!";

preg_match($pattern, $string, $matches);
print_r($matches);

结果是

Array
(
    [0] => TextToMatch [some][random][tags] SomeMoreMatches
    [1] => TextToMatch 
    [tags] => [tags]
    [2] => [tags]
    [3] =>  SomeMoreMatches
)

是否可以获得类似

的内容
Array
(
    [0] => TextToMatch [some][random][tags] SomeMoreMatches
    [1] => TextToMatch 
    [tags] => Array
        (
            [0] => [some]
            [1] => [random]
            [2] => [tags]
        )
    [2] => Array
        (
            [0] => [some]
            [1] => [random]
            [2] => [tags]
        )
    [3] =>  SomeMoreMatches
)

仅使用preg_match

我知道我可以爆炸标签,但我想知道我是否可以用preg_match(或类似的功能)来做这件事。

其他例子

$input = "Some text [many][more][other][tags][here] and maybe some text here?";

理想的输出

Array
(
    [0] => Some text [many][more][other][tags][here] and maybe some text here?
    [1] => Some text 
    [tags] => Array
        (
            [0] => [many]
            [1] => [more]
            [2] => [other]
            [3] => [tags]
            [4] => [here]
        )
    [2] => Array
        (
            [0] => [many]
            [1] => [more]
            [2] => [other]
            [3] => [tags]
            [4] => [here]
        )
    [3] =>   and maybe some text here?
)

3 个答案:

答案 0 :(得分:1)

您需要使用preg_match_all并修改reg exp:

public static void main(String[] args) {
    while (true) {
        Scanner input = new Scanner(System.in);
        System.out.print("Enter a binary number (END to exit): ");
        try {
            String inputValue = input.next();
            if (inputValue.equals("END")) {
                break;
            }
            if (!inputValue.matches("[01]+")) {
                throw new Exception("Invalid binary input");
            }

            int binarynum = Integer.valueOf(inputValue);
            int decimal = getDecimalValue(binarynum);
            System.out.println("Binary = " + binarynum + " Decimal = " + decimal);
            System.out.println();
        } catch (Exception e) {
            System.err.println(e.getMessage());
        }
    }
}

public static int getDecimalValue(int binary) {
    int decimal = 0;
    int power = 0;

    while (true) {
        if (binary == 0) {
            break;
        } else {
            int temp = binary % 10;
            decimal += temp * Math.pow(2, power);
            binary = binary / 10;
            power++;
        }
    }
    return decimal;
}

只需在preg_match_all('/(?P<tags>\[.+?\])/', $string, $matches); 之后删除+即可设置一种模式,)进行全局搜索

如果您需要发布的具体答案,请尝试:

preg_match_all

你得到:

$string = '[some][random][tags]';
$pattern = "/(?P<tags>\[.+?\])/";

preg_match_all($pattern, $string, $matches);

$matches = [
  implode($matches['tags']), end($matches['tags'])
] + $matches;

print_r($matches);

答案 1 :(得分:1)

由于您在评论中表示您实际上并不对标记集之前的主要子字符串感兴趣,并且因为您声明您不一定需要指定的捕获组(我从不使用它们),实际上只需要删除第一位,在标签集之后拆分空格上的字符串,然后拆分标签集中的每个标签。

代码:(Demo

$split = explode(' ', strstr($input, '['), 2);  // strstr() trims off the leading substring
var_export($split);                     // ^ tells explode to stop after making 2 elements

产地:

array (
  0 => '[many][more][other][tags][here]',
  1 => 'and maybe some text here?',
)

然后,分割这些方形括号标签的最直接/最干净的方法是使用每个右括号(])和每个左括号([)之间的零宽度位置。由于只有正则表达式可以将这些特定位置隔离为分隔符,因此我建议preg_split()

$split[0] = preg_split('~]\K~', $split[0], -1, PREG_SPLIT_NO_EMPTY);
var_export($split);       ^^- release/forget previously matched character(s)

这是最终输出:

array (
  0 => 
  array (
    0 => '[many]',
    1 => '[more]',
    2 => '[other]',
    3 => '[tags]',
    4 => '[here]',
  ),
  1 => 'and maybe some text here?',
)

答案 2 :(得分:0)

不,正如Wiktor所说(12),不可能只使用preg_match

正常工作的解决方案

<?php

$string = 'TextToMatch [some][random][tags] SomeMoreMatches';
$pattern = "!(TextToMatch )(?P<tags>\[.+?\]+)( SomeMoreMatches)!";

preg_match($pattern, $string, $matches);
$matches[2] = $matches["tags"] = array_map(function($s){return "[$s]";}, explode("][", substr($matches["tags"],1,-1)));
print_r($matches);