PHP正则表达式匹配多个选项

时间:2015-05-14 21:27:58

标签: php regex

我正在尝试编写一些代码,以查找以下内容:

Yesterday
Last 7 Days
Last 30 Days
This Year
Last Year

我有以下正则表达式:

/yesterday|(\d+)(?=\s+(\w+))|(\w+)(?=\s+(year))/i

使用:

preg_match("/yesterday|(\d+)(?=\s+(\w+))|(\w+)(?=\s+(year))/i", $input, $output)

我使用phpliveregex.com和preg_match获得以下结果:

array(5
0   =>  Last
1   =>  
2   =>  
3   =>  Last
4   =>  Year
)
array(5
0   =>  This
1   =>  
2   =>  
3   =>  This
4   =>  year
)
array(1
0   =>  yesterday
)
array(3
0   =>  30
1   =>  30
2   =>  days
)
array(3
0   =>  7
1   =>  7
2   =>  days

我的问题是'年'选项以及他们有空键的事实,因为我想引用$output[1]$output[2]来获取间隔和'span'(天)。一次只传递一个字符串,因此它将是上面列出的选项之一,而不是一次查找的多个选项。

如果有人能帮我找到最佳解决方案,可以返回'昨天'或('7'和'天')或('30'和'天')或''这'和'年')或''最后'和'年')非常感谢!

修改

这是我想要的输出:

'Yesterday'
$output[0] => 'Yesterday'

'Last 7 Days'
$output[0] => '7'
$output[1] => 'Days'

'Last 30 Days'
$output[0] => '30'
$output[1] => 'Days'

'This Year'
$output[0] => 'This'
$output[1] => 'Year'

'Last Year'
$output[0] => 'Last'
$output[1] => 'Year'

我正在尝试捕获处理其余代码所必需的“组”。

3 个答案:

答案 0 :(得分:1)

您刚才描述的内容可以通过以下正则表达式实现:

(yesterday|\d+(?=\s+\w+)|\w+(?=\s+year))\s*(\w*)$

在Regex101.com Demo Here上测试:

enter image description here

答案 1 :(得分:1)

您可以使用branch reset功能来避免空组:

$text = <<<'EOD'
Yesterday
Last 7 Days
Last 30 Days
This Year
Last Year
EOD;

$pattern = '~\b(?|yesterday\b|\d+(?= (days\b))|\w+(?= (year\b)))~i';
if (preg_match_all($pattern, $text, $matches, PREG_SET_ORDER))
    print_r($matches);
// or preg_match without PREG_SET_ORDER if you test the strings one by one

模式细节:

\b
(?|                     # open the branch reset group
    yesterday \b        # when this branch succeeds the capture group is not defined
  |
    \d+ (?=[ ](days\b)) # in each branch the capture group
  |
    \w+ (?=[ ](year\b)) # has the same number 
)                       # (so there is only one capture group)

结果:

Array
(
    [0] => Array
        (
            [0] => Yesterday
        )

    [1] => Array
        (
            [0] => 7
            [1] => Days
        )

    [2] => Array
        (
            [0] => 30
            [1] => Days
        )

    [3] => Array
        (
            [0] => This
            [1] => Year
        )

    [4] => Array
        (
            [0] => Last
            [1] => Year
        )

)

请注意,在构建分支重置时,必须从没有组的备选项开始,然后从具有一个组的备选项开始,然后是两个组,等等。否则,您可能会在结果中获得无用的空组。

另请注意,组0实际上不是捕获组,但它是整个匹配。

答案 2 :(得分:0)

您可以使用:

/((?:Last|This)\s+(?:\d+\s+Days|Year)|Yesterday)/

匹配

MATCH 1
1.  [0-9]   `Yesterday`
MATCH 2
1.  [10-21] `Last 7 Days`
MATCH 3
1.  [22-34] `Last 30 Days`
MATCH 4
1.  [35-44] `This Year`
MATCH 5
1.  [45-54] `Last Year`

正则表达式演示:

https://regex101.com/r/mA8jZ5/1

正则表达式解释:

/((?:Last|This)\s+(?:\d+\s+Days|Year)|Yesterday)/

1st Capturing group ((?:Last|This)\s+(?:\d+\s+Days|Year)|Yesterday)
    1st Alternative: (?:Last|This)\s+(?:\d+\s+Days|Year)
        (?:Last|This) Non-capturing group
            1st Alternative: Last
                Last matches the characters Last literally (case sensitive)
            2nd Alternative: This
                This matches the characters This literally (case sensitive)
        \s+ match any white space character [\r\n\t\f ]
            Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
        (?:\d+\s+Days|Year) Non-capturing group
            1st Alternative: \d+\s+Days
                \d+ match a digit [0-9]
                    Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
                \s+ match any white space character [\r\n\t\f ]
                    Quantifier: + Between one and unlimited times, as many times as possible, giving back as needed [greedy]
                Days matches the characters Days literally (case sensitive)
            2nd Alternative: Year
                Year matches the characters Year literally (case sensitive)
    2nd Alternative: Yesterday
        Yesterday matches the characters Yesterday literally (case sensitive)