【问题标题】:Regex match before string comes up字符串出现之前的正则表达式匹配
【发布时间】:2011-08-13 07:49:56
【问题描述】:

所以我有这个来自游戏服务器的超过 10,000 行消息的文件,如下所示:

11.07.23 08:40:16 [INFO] NC:移动违规:来自 yasmp 的 wolfman98 (-90.8, 64.0, 167.5) 到 (-90.7, 64.0, 167.3) 距离 (0.0, 0.0, 0.2)

11.07.23 10:57:44 [INFO] NC:移动违规:来自 yasmp 的 AKxiZeroDark (-1228.3, 11.2, 1098.7) 到 (-1228.3, 11.2, 1098.7) 距离 (0.0, 0.0, 0.0)

我拥有的当前正则表达式代码是:\d{1,4}\.\d{1},它匹配到目前为止所有粗体:

11.07.23 08:40:16 [INFO] NC:移动违规:来自 yasmp 的 wolfman98(-90.864.0,167.5) 到 (-90.7, 64.0, 167.3) 距离 (0.0, 0.0, 0.2)

我一直无法找到一种方法来获取仅显示的部分:

(-1228.3, 11.2, 1098.7) 到 (-1228.3, 11.2, 1098.7)

在“距离”字之前,开头没有时间戳,最终替换成这样:

11.07.23 08:40:16 [INFO] NC:移动违规:来自 yasmp 的 wolfman98 (-#, #, #)(-#, #, #) 距离 (0.0, 0.0, 0.2)

11.07.23 10:57:44 [INFO] NC:移动违规:来自 yasmp 的 AKxiZeroDark (-#, #, #)(-#, #, #) 距离 (0.0, 0.0, 0.0)

还有一点额外的信息,数字可以是负数也可以不是,范围从 1.0 位到 1234.0 位,这就是为什么我需要帮助在“距离”一词之前再次匹配。

编辑:甚至,如果整个事情没有出现也可以:

11.07.23 08:40:16 [INFO] NC:移动违规:来自 yasmp 的 wolfman98 距离 (0.0, 0.0, 0.2)

11.07.23 10:57:44 [INFO] NC:移动违规:来自 yasmp 的 AKxiZeroDark 距离 (0.0, 0.0, 0.0)

【问题讨论】:

    标签: regex string-matching


    【解决方案1】:

    扩展您的号码匹配正则表达式的相当多毛的正则表达式将是\((?:-?\d{1,4}\.\d{1}(?:, |\))){3} to \((?:-?\d{1,4}\.\d{1}(?:, |\))){3}(?= distance)。让我们稍微分解一下。

    它由两个相同的组组成,以匹配括号中的两组数字:\((?:-?\d{1,4}\.\d{1}(?:, |\))){3}。正则表达式现在允许在数字前添加可选的-,这使得数字匹配-?\d{1,4}\.\d{1}。每个数字后面都有一个逗号或括号,所以要迭代数字匹配,我们也需要它:(?:, |\))。然后,整个野兽都以\( 为前缀,以获取数字组的开头括号。该正则表达式重复两次以获得两组数字,其中 to 匹配。

    最后一位是肯定的前瞻,以确保我们匹配单词 distance 后跟的数字组。该词不会包含在匹配中,但必须存在才能使正则表达式匹配。

    我使用了非捕获组((?: ... ) 的东西),因为我不知道你想对捕获做什么。

    我已经使用 perl 5.12.2 对你的两个示例日志文件行进行了尝试,它似乎可以工作。

    【讨论】:

    • 您可以使用此正则表达式将数字替换为哈希,方法是现在提取匹配的数字,用哈希替换数字,然后重建日志行:perl -ne '/^(.*)(\((?:-?\d{1,4}\.\d{1}(?:, |\))){3} to \((?:-?\d{1,4}\.\d{1}(?:, |\))){3})(?= distance)(.*)$/ && do { my ($pre, $no_numbers, $post) = ($1, $2, $3); $no_numbers =~ s/\d+\.\d+/#/g; print "$pre$no_numbers$post\n"; }'
    【解决方案2】:

    您需要从打开序列的( 的开头到距离之前的) 的结尾进行匹配。

    未经检查的、可能过于宽泛的正则表达式可能是:\([-0-9., ]+\) to \([-0-9., ]+\),但这可能与您不想要的匹配。

    【讨论】:

    • 您还需要在括号对之间留一个空格才能匹配,即\([-0-9., ]+\) to \([-0-9., ]+\)
    【解决方案3】:
    /(?:\-|\b)\d{1,4}.\d{1}\b(?=.*distance)/
    

    匹配您想要的数字(在 PHP 中测试)。

    【讨论】:

      【解决方案4】:

      听起来像是 perl 的工作:

      use strict;
      use warnings;
      use ARGV::readonly;
      
      my $rx = qr/\([0-9,\.\- ]+\)/;
      
      while (<>) {
          s/ $rx to $rx( distance $rx\s*)$/$1/;
          print;
      }
      

      用法: script.pl input.txt &gt; output.txt

      或者作为具有更简单正则表达式的单行。只需删除前两个括号,无论它们包含什么:

      perl -pwe 's/ \([^)]+\)//; s/ \([^)]+\)//;' input.txt 
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-10-19
        • 2010-11-19
        • 1970-01-01
        • 1970-01-01
        • 2013-02-24
        • 1970-01-01
        相关资源
        最近更新 更多