如何扩展正则表达式以查找多个匹配项?

时间:2015-06-02 16:17:28

标签: php regex icalendar

这是我目前的正则表达式(用于解析 iCal 文件):

/(.*?)(?:;(?=(?:[^"]*"[^"]*")*[^"]*$))([\w\W]*)/

使用preg_match()的当前输出是:

//Output 1 - `preg_match()`
Array
(
    [0] => TZID="Greenwich Mean Time:Dublin; Edinburgh; Lisbon; London"
    [1] => VALUE=DATE;RSVP=FALSE;LANGUAGE=en-gb
)

我想扩展我的正则表达式以输出它(即找到多个匹配项):

//Output 2
Array
(
    [0] => TZID="Greenwich Mean Time:Dublin; Edinburgh; Lisbon; London"
    [1] => VALUE=DATE
    [2] => RSVP=FALSE
    [3] => LANGUAGE=en-gb
)    

正则表达式应搜索未包含在引用子字符串中的每个分号,并将其作为匹配项提供。

不能只交换到preg_match_all(),因为这会提供不需要的输出

//Output 3 - `preg_match_all()`
Array
(
    [0] => Array
        (
            [0] => TZID="Greenwich Mean Time:Dublin; Edinburgh; Lisbon; London";VALUE=DATE;RSVP=FALSE;LANGUAGE=en-gb
        )

    [1] => Array
        (
            [0] => TZID="Greenwich Mean Time:Dublin; Edinburgh; Lisbon; London"
        )

    [2] => Array
        (
            [0] => VALUE=DATE;RSVP=FALSE;LANGUAGE=en-gb
        )

)

3 个答案:

答案 0 :(得分:2)

您需要使用preg_match_all来获取字符串的所有匹配项。

您使用的模式并非旨在获得多个结果,因为[\w\W]*匹配所有内容直到字符串结尾。
但它只是你的一个问题,像这样设计的模式需要检查(对于每个冒号)引用的数量是奇数还是偶数直到文件的结尾!:(?=(?:[^"]*"[^"]*")*[^"]*$)。想象一下,使用此前瞻解析整个字符串的次数。

为了避免这个问题,您可以使用不尝试查找冒号的其他方法,但尝试描述冒号的所有内容:所以您正在寻找不包含引号或冒号+引用部分的文本,无论内容如何。

您可以使用这种模式:

$pattern = '~[^\r\n";]+(?:"[^"\\\]*(?:\\\.[^"\\\]*)*"[^\r\n";]*)*~';

if (preg_match_all($pattern, $str, $matches))
    print_r($matches[0]);

模式细节:

~           # pattern delimiter
[^\r\n";]+  #" # all that is not a newline, a double quote or a colon
(?:         # non-capturing group: to include eventual quoted parts
    "                  #"# a literal quote
    [^"\\\]*           #"# all that is not a quote or a backslash
    (?:\\\.[^"\\\]*)*  #"# optional group to deal with escaped characters
    "                  #"#
    [^\r\n";]*         #"# 
)*          # repeat zero or more times 
~

demo

答案 1 :(得分:1)

您可以使用以下内容进行匹配:

(.*?(?:;|$))(?![^"]*")

请参阅DEMO

或拆分:

;(?![^"]*")

请参阅DEMO

答案 2 :(得分:1)

(.+?)(?:;(?=(?:[^"]*"[^"]*")*[^"]*$)|$)

试试这个。看看演示。

https://regex101.com/r/pG1kU1/18