【问题标题】:Grep between two patterns in file在文件中的两个模式之间进行 Grep
【发布时间】:2023-04-04 07:47:01
【问题描述】:

例子

Date & Time : 2016-01-23 02:00:00
abc
abc
abc
Date & Time : 2016-01-24 03:00:00
abc
abc
abc
abc
Date & Time : 2016-01-25 05:00:00

我想计算两个模式之间的 abc 总数(比如 2016-01-23 和 01-24)然后(比如 2016-01-24 到 2016-01-26)。

【问题讨论】:

    标签: bash awk grep


    【解决方案1】:

    一个小状态机:

    awk '/Date & Time/ {if (n) print n; n=0; next} {n++}' file
    

    在 2 个特定日期之间

    awk -v d1="2016-01-24" -v d2="2016-01-26" '
        /Date & Time/ {if ($5 >= d1) counting = 1; else if ($5 >= d2) exit; next}
        counting {count++}
        END {print count}
    ' file
    

    【讨论】:

    • 刚刚编辑了我的问题,您能否调整答案以满足该问题。
    【解决方案2】:
    $ grep -zo 'Date & Time : 2016-01-23 02:00:00.*Date & Time : 2016-01-24 03:00:00' infile |
    > grep -zo 'abc' | wc -l
    3
    $ grep -zo 'Date & Time : 2016-01-24 03:00:00.*Date & Time : 2016-01-25 05:00:00' infile |
    > grep -zo 'abc' | wc -l
    4
    

    将文件视为二进制文件以忽略换行符 (-z) 并仅保留匹配项 (-o),然后匹配所有出现的 abc 并计算它们 (wc -l)。

    采用更好的脚本格式:

    $ pattern1='Date & Time : 2016-01-23 02:00:00'
    $ pattern2='Date & Time : 2016-01-24 03:00:00'
    $ grep -zo "$pattern1"'.*'"$pattern2" infile | grep -zo 'abc' | wc -l
    3
    

    使用 sed 的解决方案(与上面使用的模式变量相同):

    $ sed -n "/$pattern1/,/$pattern2/{/abc/p}" infile | wc -l
    3
    

    这假设每行不超过一个abc。如果有:

    sed -n "/$pattern1/,/$pattern2/p" infile | grep -o 'abc' | wc -l
    

    【讨论】:

    • 我想在 'Date & Time : 2016-01-23 02:00:00' 和 'Date & Time : 2016-01-24 03:00:00' 之间使用 wc -l 即)我需要将确切的情况放在 grep -oz'my exact pattern' 的位置。我试过但没有工作
    • @Sukan 嗯,是的,因为你现在改变了问题。
    • @Benjawin 能否请您调整一下答案,然后谢谢
    • @Sukan 我会这样做的。如果这个问题第一次反映了你实际上想要什么,那就太棒了。
    • 感谢更新的答案,但它不起作用我得到 0 作为 o/p 我试过这个,grep -zo 'Date & Time : 2016-01-23 02:00:00. *日期和时间:2016-01-24 03:00:00' infile | grep -zo 'abc' | wc -l
    【解决方案3】:

    有很多方法可以做到这一点。这是一个 awk 示例,它使用一个简单的状态来指示何时找到匹配条件 (state = 1)

    BEGIN { state = 0; count = 0; }
    /^Date \& Time : 2016-01-23 02:00:00$/ { state = 1; next; }
    /^Date \& Time : 2016-01-24 03:00:00$/ {state = 2; next; }
    /^abc$/ { if (state == 1) count++; }
    END { print "Found abc " count " times."
    

    希望这会有所帮助。我假设您的 abc 单独在线,请根据需要进行自定义。

    【讨论】:

    • 请解释逻辑
    • State = 0 表示第一个事件(日期和时间线)尚未命中。 State = 1 在命中该行时设置,并且是匹配 abc 行时的唯一状态。当第二个日期和时间事件发生时,状态设置为 2 并且不再计算 abc 行。 end 子句打印出结果。单行 sed 解决方案是我最喜欢的,前提是您的输入保持简单。
    • 感谢您的回答
    【解决方案4】:

    当然,Perl 可以做到。

    给定:

    $ echo "$tgt" 
    Date & Time : 2016-01-23 02:00:00
    abc
    abc
    abc
    Date & Time : 2016-01-24 03:00:00
    abc
    abc
    abc
    abc
    Date & Time : 2016-01-25 05:00:00
    

    在 Perl 中:

    $ echo "$tgt" | perl -0777 -lne 'while(/(^Date & Time :[\d\-: ]+)\s+(\S.*?)(?=^Date & Time :[\d\-: ]+)/gsm){$x=$2=~tr/\n//; print "$1 $x lines\n"}'
    Date & Time : 2016-01-23 02:00:00 3 lines
    Date & Time : 2016-01-24 03:00:00 4 lines
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 1970-01-01
      • 2015-08-10
      相关资源
      最近更新 更多