超过五分钟的egrep正则表达式

超过五分钟的egrep正则表达式

我的文本文件中有以下时间格式

       `1` equals one second.
    `5|01` equals five minutes and one seconds.
   `13|01` equals thirteen minutes and one seconds.
`21|12|01` equals 21 hours, 12 minutes, and 1 seconds.

我需要 egrep 任何超过五分钟的时间。我正在使用以下正则表达式,但它不起作用,因为它排除了诸如 之类的时间13|00

'[[:space:]0-9][[:space:]0-9][[:space:]|][[:space:]0-9][[:space:]6-9][|][0-9][0-9]'

这是一个例子:

 lite on       1
 lite on      01
 lite on    5|22
 lite on   23|14
 lite on 1|14|23

答案1

忽略空格(您可以稍后自己填写)和可能的前导零(同样),您希望匹配任何

[5-9]\|[0-9]+
[1-9][0-9]\|[0-9]+
[0-9]+\|[0-9]+\|[0-9]+

对于范围内的时间

[5,10) minutes
[10,99) minutes
1+ hours

分别。

因此,将它们加入到一个匹配组中,(...|...)并在开头和结尾处进行足够的锚定(这样您就不会匹配14|591|00|00)。

这给出了

grep -E 'on +([5-9]\|[0-9]+|[1-9][0-9]\|[0-9]+|[0-9]+\|[0-9]+\|[0-9]+) *$'

我们可以稍微简化一下,因为秒对于所有三个正则表达式都是通用的:

grep -E 'on +([5-9]|[1-9][0-9]|[0-9]+\|[0-9]+)\|[0-9]+ *$'

答案2

这应该有效:

grep -E '( [0-9]{1,2}\|[0-9]{1,2}\|[0-9][1-9] )|( [0-9][0-9]\|[0-9]{2,2} )|( [5-9]\|[0-9][1-9] )|( [6-9]\|[0-9][0-9] )' <file>

基本上,您正在创建 4 个模式,它们封装在' 中,并用'()分隔。||行为与or正则表达式中相同。

这些{1,2}零件是1-2 instances of preceding pattern如此[0-9]{1,2}意味着1-2 instances of 0-9

or之后,我们通过语法为所有可能的数字组合创建一个基本测试用例

答案3

不要使用grep.正则表达式用于匹配模式,但它们对于匹配值来说确实很糟糕。您也许可以做到,但您使用锤子作为螺丝刀。从技术上讲,它是可行的,但它很混乱且效率低下。

所以与其:

#!/usr/bin/env perl

use strict;
use warnings;

while (<DATA>) {
    my @numbers = m/(\d+)/g;
    my $seconds = pop(@numbers);
    $seconds += ( pop(@numbers) // 0 ) * 60;  #second digit minutes -> seconds
    $seconds
        += ( pop(@numbers) // 0 ) * 60 * 60;  #third digit, hours  -> seconds;
    print if $seconds > 300;
}

__DATA__
 lite on       1
 lite on      01
 lite on    5|22
 lite on   23|14
 lite on 1|14|23

这打印:

 lite on    5|22
 lite on   23|14
 lite on 1|14|23

您可以将其简单化为:

perl -ne 'for ( m/(\d+)/g ) { $t *= 60; $t += $_ }; print if $t > 300;'

对于奖励点 - 这可以应对相当任意的验证标准,没有太大的困难,并且如果您决定有一天 grep 获取不同的值,则不需要太多的修改。

但上面的工作原理是:

  • 使用m/(\d+)/g- 作为g匹配,意味着它将“一个或多个数字”的重复实例选择到数组中。 (@numbers或者就像第二个示例中 for 循环中的自包含迭代器一样)。
  • 它通过乘以 60 将该数字链转换为秒。(如果您添加天数,则效果不会那么好!)
  • 然后测试该数字是否大于 300 - 即 5 分钟(以秒为单位)。

相关内容