【问题标题】:PHP How to preg match this string?PHP如何预匹配这个字符串?
【发布时间】:2015-03-08 11:33:18
【问题描述】:

我有一长串 IP 地址和端口。我正在尝试从与此类似的列表中匹配端口号:

/connect=;;41.26.162.36;;192.168.0.100;;8081;;
/connect=;;98.250.16.76;;192.168.0.24;;8080;;
/connect=;;216.152.60.12;;192.168.1.103;;8090;;
/connect=;;91.11.65.110;;192.168.1.3;;8081;;

我在匹配全球 IP 地址之前没有遇到任何问题:

preg_match_all('/connect=;;(.+?);;/', $long, $ip);
            $ip = $ip[1][0];
            print_r($ip);

这对我来说非常有效,但我不知道如何预匹配位于行尾的端口。

【问题讨论】:

    标签: php regex preg-match


    【解决方案1】:

    只是稍微扩展一下上面的答案:

    if (preg_match_all('/connect=;;([\d\.]+);;([\d\.]+);;(\d+);;/',
                       $long, $matches, PREG_SET_ORDER)) {
      foreach($matches as $match) {
        list(,$ip1, $ip2, $port) = $match;
        /* Do stuff */
        echo "{$ip1} => {$ip2}:{$port}\n";
      }
    }
    

    您可以在 IP 检测方面做得更聪明一些,但如果您的样本格式良好,这应该绰绰有余。

    http://3v4l.org/FpGFD

    【讨论】:

    • 您不需要转义字符类中的点。
    【解决方案2】:

    试试这个方法...

        $re = "/connect=;;(.+?);;(\d{4});;/";
        $str = "/connect=;;41.26.162.36;;192.168.0.100;;8081;;/connect=;;98.250.16.76;;
        192.168.0.24;;8080;;/connect=;;216.152.60.12;;192.168.1.103;;8090;;/connect=;;
        91.11.65.110;;192.168.1.3;;8081;;";
    
        preg_match_all($re, $str, $matches);
    

    解释:

      /connect=;;(.+?);;(\d{4});;/g
    
       connect=;; matches the characters connect=;; literally (case sensitive)
      1st Capturing group (.+?)
        .+? matches any character (except newline)
            Quantifier: +? Between one and unlimited times, as few times as possible, 
       expanding as needed [lazy]
       ;; matches the characters ;; literally
      2nd Capturing group (\d{4})
        \d{4} match a digit [0-9]
            Quantifier: {4} Exactly 4 times
      ;; matches the characters ;; literally
      g modifier: global. All matches (don't return on first match)
    

    【讨论】:

    • 这段代码如何避免第二个(本地ip地址)?当我使用/connect=;;(.+?);;(\d{4});;/"; 时,我不断得到这个:41.26.162.36;;192.168.0.100 结果
    • 它没有。它将这两个 IP 地址混合成一个匹配的子字符串。
    【解决方案3】:

    由于您的日志将被严格可靠地格式化,您可以只扫描格式化的字符串。

    https://www.php.net/manual/en/function.sscanf.php

    sscanf() 不会像 preg_match_all() 那样产生不需要的全字符串匹配。

    代码:(Demo)

    $logs = <<<LOGS
    /connect=;;41.26.162.36;;192.168.0.100;;8081;;
    /connect=;;98.250.16.76;;192.168.0.24;;8080;;
    /connect=;;216.152.60.12;;192.168.1.103;;8090;;
    /connect=;;91.11.65.110;;192.168.1.3;;8081;;
    LOGS;
    
    foreach(explode(PHP_EOL, $logs) as $line) {
        sscanf($line, "/connect=;;%[^;];;%[^;];;%d;;", $ip1, $ip2, $port);
        var_export(
            [$ip1, $ip2, $port]
        );
        echo "\n";
    }
    

    输出:

    array (
      0 => '41.26.162.36',
      1 => '192.168.0.100',
      2 => 8081,
    )
    array (
      0 => '98.250.16.76',
      1 => '192.168.0.24',
      2 => 8080,
    )
    array (
      0 => '216.152.60.12',
      1 => '192.168.1.103',
      2 => 8090,
    )
    array (
      0 => '91.11.65.110',
      1 => '192.168.1.3',
      2 => 8081,
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-04
      • 2011-08-09
      • 1970-01-01
      • 2012-06-09
      • 1970-01-01
      相关资源
      最近更新 更多