【问题标题】:Bash: how to get lines between patterns only if there is pattern2 between themBash:仅当它们之间存在pattern2时如何在模式之间获取线
【发布时间】:2017-02-18 23:33:10
【问题描述】:

接下来的情况。我得到了日志文件,其中日志用减号分隔,例如:

Timestamp1
---
Log: 1
Address: http://addr1.com
Payload: <soap:Envelope>
             <soap:Body>
                 <context 1-1>
                 <context 1-2>
                 <context 1-3>
             </soap:Body>
         <soap:Envelope>
---;
Timestamp2
---
Log: 2
Address: http://addr2.com
Payload: <soap:Envelope>
             <soap:Body>
                 <context 2-1>
             </soap:Body>
         <soap:Envelope>
---;
Timestamp3
---
Log: 3
Address: http://addr3.com
Payload: <soap:Envelope>
             <soap:Body>
                 <context 3-1>
                 <context 3-2>
             </soap:Body>
         <soap:Envelope>
---;
...

我需要获取找到某些关键字的整个日志信息,例如如果关键字是“上下文 2-1”,则应打印下一个字符串:

---
Log: 2
Address: http://addr2.com
Payload: <soap:Envelope>
             <soap:Body>
                 <context 2-1>
             </soap:Body>
         <soap:Envelope>
---;

那么我怎样才能在它周围用“贪婪”切割分隔符进行这种模式搜索呢?

【问题讨论】:

  • 删除 ... 并展示更好的示例并展示您的尝试。

标签: bash sed grep pattern-matching


【解决方案1】:

使用 sed:

sed -n '/^---/ {:a;N;/---;/!ba;/context 2-1/p}' file

说明:

  • /^---/ 当行以 --- 开头时 找到了
  • a: 循环标签
  • N:将下一行添加到模式空间
  • /---;/!: 而---; 如果没有找到...
  • ba 循环到 a 标签
  • /context 2-1/p:当循环终止时,如果找到context 2-1,则打印之前添加到模式空间的所有行

【讨论】:

    【解决方案2】:

    以此为指导:How to select lines between two patterns?

    $0=="---" {                   # at the fron marker
        flag=1                    # flag up
        buf=""                    # clear the buf
    } 
    $0=="---;" { flag=0 }         # at the end marker, flag down
    {
        buf=buf $0 (flag?RS:"")   # gather buffer, add RS before the end marker
        if($0 ~ "^Payload2")      # if keyword found
            output=1              # output flag up
    } 
    flag==0 && output==1 {        # after end marker when putput flag up
        print buf                 # output buf
        output=0                  # output flag down
    }
    

    运行它:

    $ awk -f script.awk logfile
    ---
    Log2
    Address2 ...
    Payload2 ...
    ---;
    

    【讨论】:

    • 感谢您的回答。是的,我知道如何使用 sed 在模式之间剪切文本,但我不知道如何检查第二个模式是否存在。
    【解决方案3】:
    awk -vRS="Timestamp[0-9]+"  -v k="context 2-1"  '$0~k' file2
    

    这使用Timestamp[0-9]+ 作为换行符。 k 是您想要的关键字。如果$0 匹配关键字,则打印$0

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-09-22
      • 1970-01-01
      • 1970-01-01
      • 2014-03-13
      • 1970-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多