如何编写正则表达式从文件中选择php中的重复模式

问题描述 投票:1回答:2

使用来自具有相似行的文件的此字符串,

03/21/19 11:20 LOC3 UNA:
03/21/19 11:40 LOC2 IN: NEW BD     PN  VO    LVA
03/21/19 11:50 LOC3 OFF:
03/21/19 12:20 LOC2 IN: OLD XD     AB  VO    LVA

我需要从石灰1捕获NEW,BD,PN,VO,LVA,在第2行捕获OLD,XD,AB,VO,LVA,依此类推,忽略其他线路

这只选择最后一个'VO'术语

IN:\s(([^\s]+)\s+)+.*LVA
php regex
2个回答
3
投票

您可以匹配字符串中具有某些文本的特定文本之后的非空白文本块的出现

preg_match_all('~(?:\G(?!\A)(?=.*LVA)|IN:)\h+\K\S+~', $s, $matches)

regex demo

细节

  • (?:\G(?!\A)(?=.*LVA)|IN:) - 要么是前一场比赛的结束(后面的字符串中的LVA除了换行符之外的0+字符之外)或IN:子串(基本上,它意味着匹配IN:之后符合模式的连续子串,但只有在有LVA的情况下后来)
  • \h+ - 1+水平空格
  • \K - 匹配重置运算符
  • \S+ - 1 +非空白字符。

PHP

$s = "03/21/19 11:20 LOC2 IN: NEW BD     PN  VO    LVA";
if (preg_match_all('~(?:\G(?!\A)(?=.*LVA)|IN:)\h+\K\S+~', $s, $matches)) {
    print_r($matches[0]);
}
// => Array ( [0] => NEW [1] => BD [2] => PN [3] => VO [4] => LVA )

要获得多个匹配项,请使用捕获组将模式包装在第一个非捕获组中,然后在构建最终输出时检查子匹配项。就像是

$s = "03/21/19 11:20 LOC2 IN: NEW BD     PN  VO    LVA
03/21/19 11:20 LOC2 IN: NEW BD     PN  VO    LVA VB";
$res = [];
if (preg_match_all('~(?:\G(?!\A)(?=.*LVA)|(IN:))\h+\K\S+~', $s, $matches, PREG_SET_ORDER, 0)) {
    $tmp = [];
    foreach ($matches as $r) {
        if (count($r) > 1) {
            if (count($tmp)>0) {
                $res[] = $tmp;
                $tmp = [];
            }
        }
        $tmp[] = $r[0];
    }
    if (count($tmp)>0) {
        $res[] = $tmp;
    }
}
print_r($res);
// => Array (
//     [0] => Array ( [0] => NEW [1] => BD [2] => PN [3] => VO  [4] => A )
//     [1] => Array ( [0] => NEW [1] => BD [2] => PN [3] => VO  [4] => LVA )
// )

PHP demo


0
投票

如果字符串总是具有相同的模式,那么您可以通过在新行和": "上爆炸并使用最终值来使用预算解决方案。

$str = "03/21/19 11:20 LOC2 IN: NEW BD     PN  VO    LVA
03/21/19 11:20 LOC2 IN: OLD XD     AB  VO    LVA";

foreach(explode("\n", $str) as $line){
    $tmp = explode(": ", $line);
    $result[] = end($tmp);
}

var_dump($result);

https://3v4l.org/IbfBo

© www.soinside.com 2019 - 2024. All rights reserved.