使用awk或sed打印不同图案之间的线条

时间:2018-01-08 06:47:11

标签: bash awk sed

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

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。提前致谢。

2 个答案:

答案 0 :(得分: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。)

答案 1 :(得分:0)

如果您的Input_file与显示的示例相同,那么关注awk可能对您有帮助。

awk '/Pat2/||/Pat4/||/Pat6/{flag="";next}/Pat1/||/Pat3/||/Pat5/{flag=1;next} flag && NF{print "range"++i", "$2}'   Input_file

也添加非单线形式的解决方案。

awk '
/Pat2/||/Pat4/||/Pat6/{
  flag="";
  next
}
/Pat1/||/Pat3/||/Pat5/{
  flag=1;
  next
}
flag && NF{
  print "range"++i", "$2
}
'    Input_file

编辑: 现在根据OP的问题更改添加其他解决方案。

awk '/Pat2/||/Pat4/||/Pat6/{flag="";next}/Pat1/||/Pat3/||/Pat5/{flag=1;++i;;next} flag && NF{print "range"i", "$2}'  Input_file