【问题标题】:Customize file content display based on grep pattern基于 grep 模式自定义文件内容显示
【发布时间】:2011-01-27 05:24:48
【问题描述】:

日志文件包含大量数据,并根据数据和时间进行排序。每个日志的大小可能会有所不同。

我想在日志文件中搜索特定模式,如果模式匹配,它应该在屏幕上显示该特定日志。

任何 shell 命令都可以使用。

日志文件示例:-

07/17/2008 10:24:12.323411 >00.23
Line   441 of xx file
Dest IP Address: 192.189.52.255           Source IP Address: 192.189.52.200 

 000:   0101   0600   4D8C   444C    0000   0000   C0BD   34C8
 008:   C0BD   34C9   C0BD   34C9    0000   0000   FFFF   FFFF


07/17/2008 10:24:12.323549 >000.000138
    Use req data

 000:   0231   7564   705F   7573    7272   6571   2073   6F63

07/17/2008 10:24:12.323566 >000.000017
Local 192.189.52.200  Port 68 : Remote 0.0.0.0         Port 0

 000:   012D                                                   .-               
 000:   0000   0000   000A   0002    000A   012D               ...........-    

   0: NULNUL NULNUL NULLF  NULSTX  NULLF  SOH -               

如果我搜索特定的 IP 地址 192.189.52.200。它应该相应地显示整个事件日志,例如,

07/17/2008 10:24:12.323566 >000.000017
Local 192.189.52.200  Port 68 : Remote 0.0.0.0         Port 0

 000:   012D                                                   .-               
 000:   0000   0000   000A   0002    000A   012D               ...........-    

   0: NULNUL NULNUL NULLF  NULSTX  NULLF  -               

【问题讨论】:

    标签: linux shell unix scripting


    【解决方案1】:

    这需要 GNU AWK (gawk),因为使用正则表达式作为记录分隔符 (RS)。

    #!/usr/bin/awk -f
    BEGIN {
        pattern = ARGV[1]
        delete ARGV[1]
    
        # could use --re-interval
        d = "[0-9]"
        RS = d d "/" d d "/" d d d d " " d d ":" d d ":" d d "[^\n]*\n"
    }
    
    NR > 1 && ($0 ~ pattern || rt ~ pattern) {
        print rt
        print $0
    }
    
    {
        rt = RT # save RT for next record
    }
    

    它不漂亮,但它有效。

    像这样运行它:

    ./script.awk regex logfile
    

    例子:

    $ ./script.awk 'C0BD|012D' logfile
    
    07/17/2008 10:24:12.323411 >00.23
    
    Line   441 of xx file
    Dest IP Address: 192.189.52.255           Source IP Address: 192.189.52.200
    
     000:   0101   0600   4D8C   444C    0000   0000   C0BD   34C8
     008:   C0BD   34C9   C0BD   34C9    0000   0000   FFFF   FFFF
    
    
    
    07/17/2008 10:24:12.323566 >000.000017
    
    Local 192.189.52.200  Port 68 : Remote 0.0.0.0         Port 0
    
     000:   012D                                                   .-
     000:   0000   0000   000A   0002    000A   012D               ...........-
    
       0: NULNUL NULNUL NULLF  NULSTX  NULLF  SOH -
    
    $ ./script.awk '10:24:12.323549' logfile
    07/17/2008 10:24:12.323549 >000.000138
    
        Use req data
    
     000:   0231   7564   705F   7573    7272   6571   2073   6F63
    

    【讨论】:

    • @Dennis:谢谢,我正在使用 cygwin。当我尝试运行这个 shell 脚本时,它显示的是整个日志文件,而不是显示特定的日志事件。
    • @Thangaraj:它在 Cygwin 中对我来说很好用。您的日志文件是否有 Windows 或 Unix 行结尾? awk --version 说什么?使用您的示例数据,您尝试了哪些正则表达式?你引用了吗?
    • @Dennis: $ awk --version GNU Awk 3.1.8 $ ./script.awk '10:24:12.323549' winLogfile.txt 我也使用记事本和 vi 编辑器保存了这个日志文件.但结果是一样的。解决这个问题的任何帮助都将是可观的。
    • @Thangaraj:和我一样。我的其他问题呢?
    • @Thangaraj:对不起。我无法重现该问题或确定它不起作用的任何原因。打印任何行的唯一方法是记录是否与正则表达式匹配。例如,如果您执行./script.awk 'foobar' winLogfile.txt,则应打印 no 行(假设该字符串不在文件中)。
    【解决方案2】:

    您可以将-A[n] 标志与grep 一起使用,其中n 是匹配后的行数。例如

    grep -A6 '192.189.52.200' my.log
    

    【讨论】:

    • 不幸的是,这不适用于每个条目具有不同长度的要求
    【解决方案3】:

    如果您有 Ruby 或可能安装它,您可以编写一个脚本来解析日志文件并打印匹配的条目。这是一个应该可以工作的脚本:

    filename=ARGV[0]
    regexpArg=ARGV[1]
    unless filename and regexpArg
            puts "Usage: #{$0} <filename> <regexp>"
            exit(1)
    end
    
    dateStr='\d\d\/\d\d\/\d\d\d\d'
    timeStr='[0-9:.]+'
    whitespace='\s+'
    regexpStr = dateStr + whitespace + timeStr + whitespace + '>[0-9.]+'
    recordStart=Regexp.new(regexpStr)
    records=[]
    file=File.new(filename, "r")
    addingToRecord = false
    currentRecord = ""
    file.each_line { |line|
            match = recordStart.match(line)
            if addingToRecord
                    if match
                            records.push(currentRecord)
                            currentRecord = line
                    else
                            currentRecord += line
                    end
            else
                    if match
                            addingToRecord = true
                            currentRecord = line
                    end
            end
    }
    file.close
    regexp=Regexp.new(regexpArg)
    records.each { |r|
            if regexp.match(r)
                    puts "----------------------------------------"
                    puts r
                    puts "----------------------------------------"
            end
    }
    

    【讨论】:

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