在上一帖的实战中,我们用到了grep的"-Po"的用法。首先,我们来看看这几个参数的含义:

      -P, --perl-regexp
              Interpret  PATTERN as a Perl regular expression.  This is highly
              experimental and grep -P may warn of unimplemented features.
      
      -o, --only-matching
              Print only the matched (non-empty) parts  of  a  matching  line,
              with each such part on a separate output line.

“-P”表示采用的模式是Perl正则表达式的模式,“-o”表示只需要匹配到的内容。

像这种参数在平时是很少使用的,需要经常翻看命令手册和实例,熟悉这些用法,以备不时之需。


下面整理了几个非主流实例,通过实例熟悉下sed和awk的扩展用法。


sed

1、打印某行到某行之间的内容

[root@server01 test2]# sed -n '/lp/,/shutdown/'p passwd
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

2、转换大小写

使用\u表示大写,\l表示小写

▼把每个单词的第一个小写字母变大写:

[root@server01 test2]# sed 's/\b[a-z]/\u&/g' passwd
Root:X:0:0:Root:/Root:/Bin/Bash
Bin:X:1:1:Bin:/Bin:/Sbin/Nologin
Daemon:X:2:2:Daemon:/Sbin:/Sbin/Nologin
......

▼把所有小写变大写:

[root@server01 test2]# sed 's/[a-z]/\u&/g' passwd
ROOT:X:0:0:ROOT:/ROOT:/BIN/BASH
BIN:X:1:1:BIN:/BIN:/SBIN/NOLOGIN
DAEMON:X:2:2:DAEMON:/SBIN:/SBIN/NOLOGIN
......

▼大写变小写:

[root@server01 test2]# sed 's/[A-Z]/\l&/g' /etc/logrotate.conf
......
# rpm packages drop log rotation information into this directory
include /etc/logrotate.d
......

3、在某一行最后添加字符串

[root@server01 test2]# sed 's/\(^shutdown.*\)/\1 123abc/' passwd | grep shutdown
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown 123abc

4、删除某行到最后一行

[root@server01 test2]# sed '/shutdown/{p;:a;N;$!ba;d}' passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown

定义一个标签a,匹配shutdown这个关键词,然后N把下一行加到模式空间里,匹配最后一行时,才退出标签循环,然后命令d,把这个模式空间里的内容全部清除。

5、打印某行到某行含某个字符串的行

[root@server01 test2]# sed -n '1,10{/nologin/p}' passwd
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin


awk

1、使用外部shell变量

[root@server01 test2]# A=100
[root@server01 test2]# echo "ABCD" | awk -v GETA=$A '{print GETA}'
100

2、合并一个文件

▼第一列相同的行合并到同一行中:

[root@server01 test2]# cat a.txt
1 a1
2 a2
3 a3
4 a4
[root@server01 test2]# cat b.txt
1 b1
2 b2
3 b3
4 b4
[root@server01 test2]# awk 'NR==FNR{a[$1]=$2}NR>FNR{print $0,a[$1]}' a.txt b.txt
1 b1 a1
2 b2 a2
3 b3 a3
4 b4 a4

NR表示读取的行数,FNR表示读取的当前行数。

所以其实NR==FNR,就表示读取b.txt的时候。 同理NR>FNR表示读取a.txt的时候。

数组a其实就相当于一个map。

3、把一个文件多行连接成一行

[root@server01 test2]# a=`cat a.txt`;echo $a
1 a1 2 a2 3 a3 4 a4
[root@server01 test2]# awk '{printf("%s ",$0)}' a.txt
1 a1 2 a2 3 a3 4 a4
[root@server01 test2]# cat a.txt |xargs
1 a1 2 a2 3 a3 4 a4

4、gsub函数

[root@server01 test2]# grep 'root' passwd
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
[root@server01 test2]# awk 'gsub(/root/,"abc")' passwd
abc:x:0:0:abc:/abc:/bin/bash
operator:x:11:0:operator:/abc:/sbin/nologin

5、生成特殊结构文件

▼用awk编写生成以下结构文件的程序。( 最后列使用现在的时间,时间格式为YYYYMMDDHHMISS)  各列的值应如下所示,每增加一行便加1,共500万行。

1,1,0000000001,0000000001,0000000001,0000000001,0000000001,0000000001,2005100110101
2,2,0000000002,0000000002,0000000002,0000000002,0000000002,0000000002,2005100110101

[root@server01 test2]# awk 'BEGIN{for(i=1;i<=5000000;i++)printf("%d,%d,%010d,%010d,%010d,%010d,%010d,%010d,%d\n",i,i,i,i,i,i,i,i,strftime("%Y%m%d%H%M"))}'
1,1,0000000001,0000000001,0000000001,0000000001,0000000001,0000000001,201706282126
2,2,0000000002,0000000002,0000000002,0000000002,0000000002,0000000002,201706282126
3,3,0000000003,0000000003,0000000003,0000000003,0000000003,0000000003,201706282126
4,4,0000000004,0000000004,0000000004,0000000004,0000000004,0000000004,201706282126
5,5,0000000005,0000000005,0000000005,0000000005,0000000005,0000000005,201706282126
6,6,0000000006,0000000006,0000000006,0000000006,0000000006,0000000006,201706282126
7,7,0000000007,0000000007,0000000007,0000000007,0000000007,0000000007,201706282126
8,8,0000000008,0000000008,0000000008,0000000008,0000000008,0000000008,201706282126
9,9,0000000009,0000000009,0000000009,0000000009,0000000009,0000000009,201706282126
10,10,0000000010,0000000010,0000000010,0000000010,0000000010,0000000010,201706282126
......

6、用print打印单引号

[root@server01 test2]# awk '{print "'"'"'"$1}' a.txt
'1
'2
'3
'4

在awk中使用脱义字符\是起不到作用的,如果想打印特殊字符,只能使用'""'这样的组合才可以。

这里自左至右为单引号 双引号 双引号 单引号。其中两个单引号为一对,两个双引号为一对。想脱义$那就是'"$"' 脱义单引号那就是 '"'"'。

7、提取eth0的IP信息

[root@server01 test2]# ifconfig ens33
ens33: flags=4163  mtu 1500
        inet 192.168.137.100  netmask 255.255.255.0  broadcast 192.168.137.255
        inet6 fe80::c1d7:5856:9856:2bb8  prefixlen 64  scopeid 0x20
        ether 00:0c:29:0c:4d:a8  txqueuelen 1000  (Ethernet)
        RX packets 160327  bytes 130100204 (124.0 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 88376  bytes 52770231 (50.3 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
        
[root@server01 test2]# ifconfig ens33 | awk -F "[^0-9.]+" 'NR==2{print $2,$3,$4}'
192.168.137.100 255.255.255.0 192.168.137.255

8、合并两个文件

[root@server01 test2]# paste  a.txt b.txt
1 a1    1 b1
2 a2    2 b2
3 a3    3 b3
4 a4    4 b4
[root@server01 test2]# paste -d '+'  a.txt b.txt
1 a1+1 b1
2 a2+2 b2
3 a3+3 b3
4 a4+4 b4