假设我有一个结构良好的文本文件,其中包含以下内容(没有前导行号):
1 Mon Jun 9 00:11:47 CST 2014
2 eth0 Link encap:Ethernet HWaddr D4:BE:D9:F5:5C:0E
3 inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
4 inet6 addr: fe80::d6be:d9ff:fef5:5c0e/64 Scope:Link
5 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
6 RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
7 TX packets:250825 errors:0 dropped:0 overruns:0 carrier:0
8 collisions:0 txqueuelen:10000
9 RX bytes:365792552 (348.8 MiB) TX bytes:20648578 (19.6 MiB)
10 Interrupt:24 Memory:d6000000-d6012100
11 Tue Jun 10 05:11:47 CST 2014
12 eth1 Link encap:Ethernet HWaddr D4:BE:D9:F5:5C:10
13 inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
14 inet6 addr: fe80::d6be:d9ff:fef5:5c10/64 Scope:Link
15 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
16 RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
17 TX packets:1206000723 errors:0 dropped:0 overruns:0 carrier:0
18 collisions:0 txqueuelen:10000
19 RX bytes:1596108082 (1.4 GiB) TX bytes:2960952707 (2.7 GiB)
20 Interrupt:25 Memory:d8000000-d8012100
现在我需要的是使用 grep 关键字“eth”过滤 eth0 部分的第 1、#3、#6 行和 eth1 部分的第 #11、#13、#16 行。
Mon Jun 9 00:11:47 CST 2014
inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
Tue Jun 10 05:11:47 CST 2014
inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
我怎样才能做到这一点?
答案1
这对我有用:
sed -n '/eth/{n;p;n;n;n;p;}' file
- 搜索字符串
eth
n;
: 跳过一行,p;
: 打印该行n;n;n;
: 跳过3行并再次打印
编辑:
这将打印上面的行、后面的行以及 3 行之后的行:
sed -n -e '/eth/{x;1!p;g;$!n;p;n;n;n;p;D;}' -e h file
你的第二个问题:我认为你可能不会输入 20 次命令n;
......
答案2
试试这个 awk 命令,
$ awk '$1~/^eth/ {getline; print; getline; getline; getline; print}' file
inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
更新:
$ awk '$1~/^eth/ {print previous; getline; print; getline; getline; getline; print}{previous=$0}' file
Mon Jun 9 00:11:47 CST 2014
inet addr:10.179.113.125 Bcast:10.179.113.127 Mask:255.255.255.248
RX packets:1169385 errors:0 dropped:0 overruns:0 frame:0
Tue Jun 10 05:11:47 CST 2014
inet addr:10.254.4.1 Bcast:10.254.4.255 Mask:255.255.255.0
RX packets:3806158038 errors:0 dropped:23193484 overruns:0 frame:0
答案3
这是一种使用 Perl 的不同方法,可以让您更灵活地选择要打印的行:
perl -n00E '
@eth_records= grep {/eth/} split/(?=>Mon|Tue|Wed|Thu|Fri|Sat|Sun)/;
@lines_to_print = qw{1 3 6};
map { $_-- } @lines_to_print;
$sep = "-"x80;
for(@eth_records){
say $sep;
say for (split/\n/)[ @lines_to_print ];
say $sep
}' your_file
这会将文件分割成以一天名称开头的行记录,并打印所有匹配记录的第 1、3 和 6 行/eth/
请注意,它会将整个文件加载到内存中,因此如果您的文件很大,请避免使用它。
答案4
以下是一些建议:
grep
grep -P 'CST|inet |RX p' file
CST
这将打印包含或inet
后跟空格或的所有行RX pa
。激活-P
Perl 兼容正则表达式,让我们可以将其用作|
逻辑 OR。您也可以使用以下任一方法实现相同的目标grep -E 'CST|inet |RX p' file
或者
grep 'CST\|inet \|RX p' file
sed
sed -n '/CST\|inet \|RX p/p' file sed -rn '/CST|inet |RX p/p' file
与上面的想法相同,
-n
抑制打印任何行,并//p
打印那些与模式匹配的行。perl
您可以在 Perl 中使用相同的方法:
perl -ne 'print if /CST|inet |RX p/' file
或者你可以做类似的事情
perl -ne '$k=1 if /CST/; print if $k==1||$k==3||$k==6; $k++' file
此处,
$k
如果该行匹配,则该变量设置为 1CST
,并且在读取每行后该变量会增加 1。如果该行$k
的值为 1,3 或 6,则打印该行。这是一种更具可扩展性的方法。另一种方法是,假设您知道要打印的行号,则直接直接打印它们(
$.
是当前行号):perl -ne 'print if $.==1||$.==3||$.==6||$.==11||$.==13||$.==16' file
或者,更惯用的说法是:
perl -ne '@d=(1,3,6,11,13,16); print if $.~~@d' file
最后,您还可以将整个文件加载到内存中并仅打印您关心的行:
perl -e '@F=<>; print @F[0,2,5,10,12,15]' file
awk
awk
您可以在whereNR
是当前行号中使用相同的基本方法:awk '/CST|inet |RX p/' file
或者
awk '{if(/CST/){k=1} if(k==1||k==3||k==6){print} k++;}' file
或者
awk 'NR==1||NR==3||NR==6||NR==11||NR==13||NR==16' file