sed和awk命令是Unix / Linux操作系统上面文本处理的强大命令:sed把文本以“ 行 ”为级别来进行就像数据库里面增删改查一样的操作;awk把一条条文本行分割为若干个“ 字段 ”,然后对这些字段进行操作。对于这两个命令,我是在《鸟哥的Linux私房菜-基础学习篇》(https://book.douban.com/subject/4889838/)这本Linux案头书里面学到的,工作中也常常会用到这两个命令,使用过程中也没碰到过什么问题。
但是最近在写脚本时却出了状况,就是我要往sed和awk里面传入外部变量。按照书里面的介绍,这两个命令的动作部分需要放到一对单引号“ ' ”里面(P358页和P365页)。如大家所知,Shell是不解释单引号字符串里面的引用的,这下让我犯了难。
后来查了一下资料,找到了办法:sed后面的动作是可以使用双引号的(使用双引号当然就可以传入外部变量了);awk可以通过“ -v ”参数传入外部变量。
首先示例sed,这里简单做一个外部引用地替换。
root@ubuntu:~# cat /etc/passwd | grep ^systemd
systemd-timesync:x:100:102:systemd Time Synchronization,,,:/run/systemd:/bin/false
systemd-network:x:101:103:systemd Network Management,,,:/run/systemd/netif:/bin/false
systemd-resolve:x:102:104:systemd Resolver,,,:/run/systemd/resolve:/bin/false
systemd-bus-proxy:x:103:105:systemd Bus Proxy,,,:/run/systemd:/bin/false
root@ubuntu:~# rep=UbuntuSystem
root@ubuntu:~# cat /etc/passwd | grep ^systemd | sed "1, \$s/systemd/${rep}/g"
UbuntuSystem-timesync:x:100:102:UbuntuSystem Time Synchronization,,,:/run/UbuntuSystem:/bin/false
UbuntuSystem-network:x:101:103:UbuntuSystem Network Management,,,:/run/UbuntuSystem/netif:/bin/false
UbuntuSystem-resolve:x:102:104:UbuntuSystem Resolver,,,:/run/UbuntuSystem/resolve:/bin/false
UbuntuSystem-bus-proxy:x:103:105:UbuntuSystem Bus Proxy,,,:/run/UbuntuSystem:/bin/false
然后是awk的示例,这里假设用awk打印机器的硬件配置。
root@ubuntu:~# cpu=$(lscpu | sed -ne '4p' | awk '{ print $2 }')
root@ubuntu:~# mem=$(free -h | sed -ne '2p' | awk '{ printf "%.0f\n", $2 }')
root@ubuntu:~# echo | awk -v cpus=${cpu} -v mems=${mem} '{ print "My Linux is "cpus" CPU(s) / "mems"G Memory." }'
My Linux is 2 CPU(s) / 2G Memory.
需要留意的是,不同于sed,awk的动作部分不能使用双引号,即单引号是保留符号。
root@ubuntu:~# lscpu | sed -ne '4p'
CPU(s): 2
root@ubuntu:~# lscpu | sed -ne '4p' | awk "{ print $2 }"
CPU(s): 2
root@ubuntu:~# lscpu | sed -ne '4p' | awk '{ print $2 }'
2
所以,鸟哥的书上写的还是有不严谨的地方,可能正如他对这本书的定位“ 基础学习 ”,于是对这两个命令写的比较简单和绝对,而sed用法的介绍有一些误导。以后看书和学习的过程中,还是要多多怀疑多多扩展多多实践才行啊!