获取linux中最后一次出现的单词的行

获取linux中最后一次出现的单词的行,linux,bash,grep,Linux,Bash,Grep,我有两个值“usb 1-3”和“地址20”。现在我试图搜索一个文本文件(基本上是一个日志文件),其中包含这两个单词 现在,该文件有许多行,其中包含以下文字: Apr 27 13:30:55 box2 kernel: usb 1-3: USB disconnect, address 20 and Apr 27 13:25:43 box2 kernel: usb 1-3: new high speed USB device using ehci_hcd and address 20 现在我的要求是

我有两个值“usb 1-3”和“地址20”。现在我试图搜索一个文本文件(基本上是一个日志文件),其中包含这两个单词

现在,该文件有许多行,其中包含以下文字:

Apr 27 13:30:55 box2 kernel: usb 1-3: USB disconnect, address 20
and
Apr 27 13:25:43 box2 kernel: usb 1-3: new high speed USB device using ehci_hcd and address 20
现在我的要求是:我想得到这两个单词倒数第二个出现的那一行,然后是接下来的16行。比如,如果文件中有6个匹配项(这两个单词都有6行),那么我需要第5个匹配项和后面的16行。如果有10个引用,那么我需要第9个引用和接下来的16行

目前我正在使用

egrep -A 20 'usb 1-3:.*address 20' filename | tail -16 > output.
但它给了我最后一次机会。不是倒数第二。请注意,这行应该有两个字,并且顺序相同(先是usb 1-3,后是地址20)
如果我的问题不清楚,请告诉我。提前感谢。

这需要两次传球,但应该可以做到:

tail -n +`egrep -n 'usb 1-3:.*address 20' filename |
  tac | sed -n '2s/:.*//p'` filename | head -17

您可以使用
awk
perl
一次性完成,但需要管理一些缓冲区。请注意,它使用了
tac
,这是一种反向
cat
。如果您的系统上没有它,请尝试将
tail-r
放到它的位置。

使用
perl
的单向操作:

use warnings;
use strict;

die qq[Usage: perl $0 <input-file>\n] unless @ARGV == 1;

my (@lines, $found);

## Reverse content and pipe output to perl.
open my $fh, q[-|], qq{tac $ARGV[0]} or die qq[Open error: $!\n];

## Read line by line.
while ( <$fh> ) { 

    ## Remove trailing '\n'.
    chomp;

    ## Use an array as a FIFO structure and save last 16 lines
    ## processed.
    if ( @lines > 16 ) { 
        pop @lines;
    }   
    unshift @lines, $_; 

    ## Count how many lines matches at same time 'usb 1-3' and
    ## 'address 20'.
    if ( m/usb\s1-3/ && m/address\s20/ ) { 
        ++$found;
    }   

    ## In second one, print lines saved.
    if ( ($found || 0) == 2 ) { 
        printf qq[%s\n], join qq[\n], @lines; 
    }   
}
使用警告;
严格使用;
除非@ARGV==1,否则死掉qq[用法:perl$0\n];
我的(@lines,$find);
##将内容和管道输出反转为perl。
打开我的$fh,q[-|],qq{tac$ARGV[0]}或死亡qq[打开错误:$!\n];
##逐行阅读。
而{
##删除尾部“\n”。
咀嚼;
##使用数组作为FIFO结构并保存最后16行
##已处理。
如果(@lines>16){
弹出@行;
}   
取消移动@行,$\;
##计算同时与“usb 1-3”匹配的行数,并
##“地址20”。
如果(m/usb\s1-3/&&m/address\s20/){
++$found;
}   
##在第二种情况下,打印行已保存。
如果($found | | 0)==2){
printf qq[%s\n],加入qq[\n],@lines;
}   
}
如果您有GNU grep

grep -B 1 -A 15 'usb 1-3.*address 20' filename

很抱歉,它不能正常工作。给出一些混合类型的线条。不是我需要的。。。在我的需求日志文件中,显示了时间“13:25:43”的行,但在您给定的语法中,我得到了一些行13:16:29,然后是一些行。13:12:22我看不到您的输入。但让我解释一下它是如何工作的。它只找到所有匹配的行(
egrep
),获取倒数第二个匹配的行号(
tac
sed
),从该行号开始跟踪整个文件(
tail
),并吐出这些行中的前17行(
head
)。也许你可以用你的数据来尝试这些步骤,看看哪里出了问题。首先检查grep。好的,我知道你哪里做错了。你的第一部分是完美的获得行号。但在那之后,当你试图跟踪的时候,那就错了。例如就我而言,是119号线。现在,当我输入“tail-119 filename”时,它给出了最后119行。这里它出错了。相反,它应该跳过前118行,然后给出接下来的17行(包括那一行)啊,是的。谢谢。那应该是从第1234行开始的
tail-n+1234
。谢谢调试。我已经用这三个缺少的字符更新了答案!这如何识别模式的倒数第二次出现?我看到这里发生了什么。这是“用户未知”问题第二版的最佳选项“但它根本没有解决最初的问题。“用户未知”我认为你已经实质性地改变并误解了这个问题。我试图在不改变内容的情况下澄清这个问题。谢谢大家的努力。