【问题标题】:Php preg_match optional groupphp preg_match 可选组
【发布时间】:2019-11-20 04:21:24
【问题描述】:

我写了一个正则表达式:

(^.*)(\[{1}[0-9]+:[0-9]+:[0-9]+:[0-9]+\]{1}) (\"{1}.+\"{1}) ([0-9]+) ([0-9-]+)

匹配一个字符串,如:

141.243.1.172 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233

并使用 php preg_match。

当我从字符串中删除例如第一部分 141.243.1.172 时,preg_match 返回我:

array(6
 0  =>  [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233
 1  =>  // correctly empty
 2  =>  [29:23:53:25]
 3  =>  "GET /Software.html HTTP/1.0"
 4  =>  200
 5  =>  233
 )

索引 1 正确为空的位置。 但是,如果我从字符串 [29:23:53:25] 中删除,我会从 preg_match 中得到一个空数组。我怎样才能得到与上面相同的结果,只让相关索引为空而不是全部?

【问题讨论】:

  • 您的正则表达式在最后一种情况下不再匹配,preg_match() 返回您似乎没有检查的0。可选匹配项必须如此标记,但在此之前请解释您对{1} 的使用,这是多余的。
  • 我用 {1} 指定我只想要一个
  • 是的 preg_match 不再匹配,有没有办法制作可选组?
  • Regex optional group的可能重复

标签: php regex


【解决方案1】:

对于由于.* 而起作用的第一部分。如果您还希望能够删除第二部分,则可以使这两个组都是可选的,而第一个是非贪婪的。也将空间移到第二组。

请注意,您不必转义双引号,并且量词 {1} 是多余的,因此可以省略。

在第一个匹配之后只有一个双引号,但为了防止可能的过度匹配,您可以使该匹配也非贪婪或使用否定字符类 ("[^"]+") 代替以防止不必要的回溯。

(^.*?)?(\[[0-9]+:[0-9]+:[0-9]+:[0-9]+\] )?(".+?") ([0-9]+) ([0-9-]+)

Regex demo

例如

$strings = [
    '141.243.1.172 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233',
    '[29:23:53:25] "GET /Software.html HTTP/1.0" 200 233',
    '"GET /Software.html HTTP/1.0" 200 233'
];

$pattern = '/(^.*?)?(\[[0-9]+:[0-9]+:[0-9]+:[0-9]+\] )?(".+?") ([0-9]+) ([0-9-]+)/';

foreach ($strings as $string) {
    preg_match($pattern, $string, $matches);
    print_r($matches);
}

结果

Array
(
    [0] => 141.243.1.172 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233
    [1] => 141.243.1.172 
    [2] => [29:23:53:25] 
    [3] => "GET /Software.html HTTP/1.0"
    [4] => 200
    [5] => 233
)
Array
(
    [0] => [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233
    [1] => 
    [2] => [29:23:53:25] 
    [3] => "GET /Software.html HTTP/1.0"
    [4] => 200
    [5] => 233
)
Array
(
    [0] => "GET /Software.html HTTP/1.0" 200 233
    [1] => 
    [2] => 
    [3] => "GET /Software.html HTTP/1.0"
    [4] => 200
    [5] => 233
)

Php demo

【讨论】:

  • 请注意,您确实应该有一个 PHP 演示设置,因为纯正则表达式与工作 PHP 脚本不同。
  • 我试过你的解决方案,但它放在同一个索引 141.243.1.172 [29:23:53:25] 中。虽然我想将它们放在单独的索引中
  • @StefanoMaglione 你是对的,我已经更新了答案。
  • @TimBiegeleisen 好建议,谢谢!我看到第一个模式不正确。
  • 我看到它有效,但如果我删除 '200' 或 '233' 或 'GET /Software.html HTTP/1.0' 我对空数组有同样的问题
【解决方案2】:

将正则表达式更改为此

((^.*)(\[{1}[0-9]+:[0-9]+:[0-9]+:[0-9]+\]{1}) )?(\"{1}.+\"{1}) ([0-9]+) ([0-9-]+)

对于 141.243.1.172 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233

结果是

Array
(
    [0] => 141.243.1.172 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233
    [1] => 141.243.1.172 [29:23:53:25] 
    [2] => 141.243.1.172
    [3] => [29:23:53:25]
    [4] => "GET /Software.html HTTP/1.0"
    [5] => 200
    [6] => 233
)

对于 [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233

结果是

Array
(
    [0] => [29:23:53:25] "GET /Software.html HTTP/1.0" 200 233
    [1] => [29:23:53:25] 
    [2] => 
    [3] => [29:23:53:25]
    [4] => "GET /Software.html HTTP/1.0"
    [5] => 200
    [6] => 233
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-16
    相关资源
    最近更新 更多