【问题标题】:Improving a working regex to match multiple lines改进工作正则表达式以匹配多行
【发布时间】:2020-12-12 12:10:50
【问题描述】:

我正在尝试从旧的 DOS 转储中匹配用户,以便他们可以迁移到新的东西。它们以% 符号开头,以] 结尾。一些在一条线上,另一些则跨越多条线。

https://regex101.com/r/0h5ndW/1

我的正则表达式%([^\%]*)] 有效,但是有没有更好的方法来选择从%](包括%])的每个用户,这样我就可以让他们通过preg_replace并在以后操纵它们?

我对多线部分有点怀疑。

Expected Output

%user:100 [     type=admin,     added=10/12/1997,     last-login:10/20/1997,     total-logins:45,     status:1 ]
%user:111 [     type=user,     added=10/12/1997,     last-login:10/27/1997,     total-logins:145,     status:1 ]
%user:112 [ type=viewer, added=10/12/1997,     last-login:10/23/1997,     total-logins:6,     status:1 ]
%user:113 [ type=viewer, added=10/12/1997,  last-login:10/14/1997,  total-logins:2, status:1]
%user:114 [ type=viewer, added=10/12/1997,  last-login:10/14/1997,  total-logins:1, status:1]
%user:115 [ type=viewer, added=10/12/1997,  last-login:10/12/1997,  total-logins:1, status:1 ]

原始数据

%user:100 [
    type=admin,
    added=10/12/1997,
    last-login:10/20/1997,
    total-logins:45,
    status:1
]

%user:111 [
    type=user,
    added=10/12/1997,
    last-login:10/27/1997,
    total-logins:145,
    status:1
]

%user:112 [ type=viewer, added=10/12/1997,
    last-login:10/23/1997,
    total-logins:6,
    status:1
]

%user:113 [ type=viewer, added=10/12/1997,  last-login:10/14/1997,  total-logins:2, status:1]

%user:114 [ type=viewer, added=10/12/1997,  last-login:10/14/1997,  total-logins:1, 
status:1]

%user:115 [ type=viewer, added=10/12/1997,  last-login:10/12/1997,  total-logins:1, 
status:1
]

【问题讨论】:

    标签: php regex


    【解决方案1】:

    您可以使用此正则表达式进行搜索:

    ((?:^%|(?!\A)\G).*)\R(?=[^][]*])
    

    并将其替换为:

    $1
    

    Updated RegEx Demo

    PHP 代码:

    $repl = preg_replace('/((?:^%|(?!\A)\G).*)\R(?=[^][]*])/m', '$1', $str);
    

    正则表达式详细信息:

    • (: 开始捕获组 #1
      • (?:^%|(?!\A)\G):在行首匹配 % 或从前一个匹配的结尾重新开始匹配。 \G 在上一个匹配的结尾或第一个匹配的字符串的开头断言位置。
      • .*: 匹配同一行中的所有内容
    • ): 结束捕获组 #1
    • \R: 匹配任何类型的换行符
    • (?=[^][]*]):确保前面有一个],中间没有匹配[]

    【讨论】:

    • 两个小观察...]RegEx Demo 中似乎不匹配,%user:113 根本不匹配...这正常吗?跨度>
    • 两者都是期望的行为。 1. ] 不应该匹配,因为我们在 ] 之前删除了换行符。 2. %user:113 不匹配,因为它已经在一行中。
    【解决方案2】:

    另一种选择是使用您尝试使用否定字符类的模式的变体来匹配%,并从开始的[ 到结束的]

    然后每次匹配删除换行符。

    ^%[^][]*\[[^][]*]$
    

    说明

    • ^ 字符串开始
    • %[^][]* 匹配 % 和 0+ 次除 [] 以外的任何字符
    • \[[^][]*] 匹配从 [ 直到结束 ]
    • $断言字符串结束

    Regex demo | Php demo

    例如

    $result = preg_replace_callback("/^%[^][]*\[[^][]*]$/m", function($m) {
        return str_replace(PHP_EOL, "", $m[0]);
    }, $data);
    

    【讨论】:

      【解决方案3】:

      作为正则表达式的替代方法,这只是使用] 拆分数据。然后修剪每一行并用空格替换新行(使用PHP_EOL)...

      $output = explode("]", $data);
      array_pop($output);
      array_walk($output, function(&$data) {
          $data = str_replace(PHP_EOL, " ", trim($data)."]");
      });
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2017-07-26
        • 1970-01-01
        • 1970-01-01
        • 2021-12-11
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多