【问题标题】:print lines between different patterns using awk or sed使用 awk 或 sed 在不同模式之间打印行
【发布时间】:2018-01-08 06:47:11
【问题描述】:

我有一个如下所示的文件:

Pat1

Id1.1 IP1.1 Desc1.1
Id1.2 IP1.2 Desc1.2
Id1.3 IP1.3 Desc1.3
Id1.4 IP1.4 Desc1.4
Id1.5 IP1.5 Desc1.5


Pat2
Id2 IP2 Description2

Pat3
Id3 IP3 Description3

Pat4
Id4 IP4 Description4

Pat5
Id5 IP5 Description5

Pat6
Id6 IP6 Description6

文件继续。我感兴趣的是提取 Pat1 和 Pat2、Pat3 和 Pat4 以及 Pat5 和 Pat6 之间的 IP。因此,经过重新格式化后的输出应该是这样的:

Output:

range1, IP1.1
range1, IP1.2
range1, IP1.3
range1, IP1.4
range1, IP1.5
range2, IP3
range3, IP5

我已经编写了以下代码,但我想通过使用更少的代码来缩小它以获得相同的输出。请看下面的代码:

awk 'flag{ if (/Pat2/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /Pat1/{flag=1}' ripe.txt > IPs.txt

awk '!/^$/' IPs.txt > IPs.csv

awk '!/[a-z]/' IPs.csv > tmp && mv tmp IPs.csv

awk '{print "range1,"$2}' IPs.csv > done.csv

awk 'flag{ if (/Pat4/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /Pat3/{flag=1}' ips.txt > A1.txt

awk '!/^$/' IPs.txt > IPs.csv

awk '!/[a-z]/' IPs.csv > tmp && mv tmp IPs.csv

awk '{print "range2,"$2}' IPs.csv >> done.csv

awk 'flag{ if (/Pat6/){printf "%s", buf; flag=0; buf=""} else buf = buf $0 ORS}; /Pat5/{flag=1}' ips.txt > A1.txt

awk '!/^$/' IPs.txt > IPs.csv

awk '!/[a-z]/' IPs.csv > tmp && mv tmp IPs.csv

awk '{print "range3,"$2}' IPs.csv >> done.csv

如您所见,我想通过迭代模式对来减少重复的代码块,并灵活地在每个 IP 范围之前添加 range1、range2 和 range3 作为 column1。提前致谢。

【问题讨论】:

    标签: bash awk sed


    【解决方案1】:

    对于每个模式对Pat1Pat2

    $ sed  '/^Pat1$/,/^Pat2$/!d;//d' input.txt | tee output.txt
    
    Id1.1 IP1.1 Desc1.1
    Id1.2 IP1.2 Desc1.2
    Id1.3 IP1.3 Desc1.3
    Id1.4 IP1.4 Desc1.4
    Id1.5 IP1.5 Desc1.5
    

    (请随意标记... | grep . 以省略空行、进一步过滤等)。

    您可以根据需要复制/粘贴和替换Pat1Pat2,或者使用变量,这成为正确引用以禁用特殊字符同时仍允许变量替换的练习,

    a='Pat2'
    b='Pat3'
    sed  '/^'"${a}"'$/,/^'"${b}"'$/!d;//d' input.txt >> output.txt
    

    请注意,我还将附加范围“附加”到output.txt(也可以通过... | tee -a output.txt,如果您还希望将输出显示到控制台)。

    【讨论】:

    • 非常感谢!添加更多命令可以提供预期的输出。
    • 如果我想从数组中传递变量怎么办? (例如 arr=(a b c d e f)),然后每两个元素执行 sed。谢谢
    • 处理变量对在 bash 中有点痛苦,除非它们有一些相似的基本子字符串,例如 for x in a b c; do echo "${x}_1 , ${x}_2"; done 或通过某些输入使用 read x y 的东西(但如果有也输出);或通过两个具有匹配索引的数组(对不起,这里没有简单的答案)*.com/questions/28725333/…*.com/questions/11215088/…
    • 我听到了,因为我尝试了您刚才提到的内容,但说起来并不容易。感谢您提供宝贵的信息。
    最近更新 更多