【问题标题】:Using awk or sed how can i print between the pattern (same pattern) only when the text in the middle of the pattern matches仅当模式中间的文本匹配时,如何使用 awk 或 sed 在模式(相同模式)之间打印
【发布时间】:2023-10-30 21:03:01
【问题描述】:

仅当模式中间的文本匹配时,如何使用 awk 或 sed 在模式(相同模式)之间打印 例如假设文件包含

# Wed 10/12/2015
field1=a
field2=b
field3=c
field4=d
# Wed 10/12/2015
field1=e
field2=f
field3=g
field4=h
# Wed 10/12/2015
field1=i
field2=j
field3=k
field4=l

我希望打印两个 '#' 之间的块,其中 field3=g 我写的下面的脚本不起作用

awk '$0 ~ /^#/{
       start_flag=1;
    }
    $0 ~ /g$/{
       mid_flag=1;
    }
    start_flag {
            n=NR;
            lines[NR];  
    }
    $0  ~ /^#/
    {
       if (start_flag && mid_flag)
       {
            for (i=n; i<NR; i++)
            print lines[i];
       }
       start_flag=0;
       mid_flag=0;
       delete lines
    }' <file_name>

预期的 o/p 是

field1=e
field2=f
field3=g
field4=h

【问题讨论】:

    标签: shell unix awk sed


    【解决方案1】:
    $ awk -v RS='#[^\n]*\n' -v ORS='' '/field3=g/' ip.txt 
    field1=e
    field2=f
    field3=g
    field4=h
    
    • -v RS='#[^\n]*\n' 将输入记录分隔符设置为 # 直到并包括下一个换行符
    • -v ORS='' 设置输出记录分隔符为空字符串
    • /field3=g/打印所有包含文本field3=g的记录


    @NeronLeVelu 提出替代方案以确保# 在行首匹配

    awk -v RS='(^|\n)[[:blank:]]*#[^\n]*\n' '/field3=g/' ip.txt
    

    【讨论】:

    • 也许只是在 RS 中添加一个starting^,以防插入符号在字段行内容中(只是为了保护,因为 OP 指定了“示例假设”,它没有t改变你非常有效的解决方案)
    • @NeronLeVelu 我检查了,但 ^ 锚定只匹配文件的开头...
    • 对,它在文件/流级别,而不是记录级别,我尝试使用 (^|\n)[[:blank:]]*#[^\n]*\n,似乎在这里工作
    【解决方案2】:

    使用grep的另一种解决方案

    grep -A1 -B2 "field3=g" file
    

    -A-B 选项在匹配行之后和之前打印 NUM 行尾随上下文。

    你明白了,

    field1=e
    field2=f
    field3=g
    field4=h
    

    仅供娱乐

    如果,您想使用sed 打印所有相邻记录以匹配field3=g

    sed -n '/^#/{
        :c; :a; n; H; 
        /^#/{bc}; 
        /field3=g/{x; s/.*#[^\n]*\n//;p;:d;n;/^#/{bc}; p; bd}; ba;
    };:b' file
    

    你明白了,

    field1=e
    field2=f
    field3=g
    field4=h
    

    或使用awk

    awk '
        /^#/{i=0; f=0} 
        {m[++i]=$0} 
        /field3=g/{for(j=2; j<=i; ++j) print m[j]; f=1; next}
        f' file
    

    你得到相同的结果

    【讨论】:

    • 如果 # 之间的字段数相同,即 4 个字段,这可能会起作用,但在我的情况下,每个块中的字段数不相同。有时 5 ,有时 4 等等
    • 我使用sed 发布了另一个解决方案,提出了新的要求
    • 我使用awk 发布了另一个解决方案,提出了新的要求