简介
本文主要介绍 Linux 系统的两个神级工具:sed 和 awk ,他们是Linux高手们必备的技能,很值得我们去研究的东西。
这里是我在网上书上收集的相关资料,因为这两个工具很有名也很重要,所以这些资料会帮助我更好的了解和熟悉它们。
在《sed and awk》一书中(1.2 A Stream Editor)的解释是:
Sed本质上是一个编辑器,但是它是非交互式的,这点与VIM不同;同时它又是面向字符流的,输入的字符流经过Sed的处理后输出。这两个特性使得Sed成为命令行下面非常有用的一个处理工具。
Sed本身是一个管道命令,可以分析 standard input 的,主要是用来分析关键字的使用、统计等,此外还可以将数据进行替换、删除、心中、选取特定行等功能。
sed命令的语法如下所示:
sed [-nefr] [动作]
参数说明:
动作说明: [n1],[n2] function
n1,n2:不见得会存在,一般代表选择进行动作的行数。 举例来说:如果我的动作是需要在 10 到 20 行之间进行的,则“10,20[动作行为]”
function 有下面这些参数:
nl /etc/passwd | sed '2,5d'
说明:
注:$表示最后一行。
nl /etc/passwd | sed '2a drink tea'
说明:
注:2a 中的 a 是指第二行后面,而 2i 中的 i 则是指第二行的前面。
nl /etc/passwd | sed '2a drink tea or ......\
drink beer'
说明:
nl /etc/passwd | sed '2, 5c No 2-5 number'
说明:
nl /etc/passwd | sed -n '5,7p'
说明:
sed 's/要被替换的内容/新的内容/g'
说明:
下面是记录一次获取IP数据的过程:
第一步:先查看源信息,利用 /sbin/ifconfig 查询 IP。
/sbin/ifconfig eth0
注:我们的目的是要获得IP数据,那么先利用关键字找出那一行。
第二步:利用关键字配合 grep 选取出关键的一行数据。
/sbin/ifconfig eth0 | grep 'inet addr'
注:因为只需要IP数据,所以接下来就是把不需要的内容都删掉,那么就需要一个正则表达式来帮助实现:
^.*inet addr:
第三步:将 IP 前面的部分予以删除
/sbin/ifconfig eth0 | grep 'inet addr' | \
sed 's/^.*inet addr://g'
注:上面的命令就把 IP 前面的数据删掉了,那么接下来就是把 IP 后面的数据也删掉,此时的正则表达式则是:
Bcast.*$
第四步:将 IP 后面的部分予以删除
/sbin/ifconfig eth0 | grep 'inet addr' | \
sed 's/^.*inet addr://g' | sed 's/Bcast.*$//g'
这样就能把 IP 截取出来了~~~
这里主要是展示 sed 与正则表达式的配合使用。
假设我想在一个文件(你自己新建或者已有的,主要是测试而已)获取MAN字样的那几行数据,但是#在内的批注我不需要,而且空白行也不要。
第一步:先使用 grep 将关键字 MAN 所在行取出来。
cat /home/man.config | grep 'MAN'
第二步:删除掉批注之后的数据。
cat /home/man.config | grep 'MAN' | sed 's/#.*$//g'
第三步:那么接下来就是把空白行删除掉。
cat /home/man.config | grep 'MAN' | sed 's/#.*$//g' | \
sed '^$/d'
首先要特别提醒的是,要练习 sed 修改文件内容的时候不能用任何系统配置文件,最好是自己新建一个测试文本来测试练习。
sed -i '/s\.$/\!/g' test.txt
说明:
sed -i '$a # This is a test' test.txt
说明:
简单来说,awk 是一个数据处理工具。
相比于 sed 常常作用于一整行的处理,awk 则比较倾向于将一行分成数个“字段”来处理。因此,awk 相当适合处理小型数据的数据处理。
对于编程语言来讲,awk 是一种便于使用且表达能力强的程序设计语言,可应用于各种计算和数据处理任务。
基本语法
awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
last -n 5 // 仅取出登陆者的数据前五行(last 可以将登陆者的数据取出来)
如果我还要在这些信息中取出:账号与登陆者的IP,且账号与IP之间以[tab]隔开,那么可以这么改命令:
last -n 5 | awk '{print $1 "\t" $3}'
上面是 awk 最常使用的动作,通过 print 的功能来讲字段的数据列出来,字段的分割则以空格键或者[tab]按键来隔开。
上面的例子中,在每一行的每个字段都是有变量名称的,那就是2等变量名称。
备注:$1 指的就是第一列,但是 $0 则是代表一整行(第一行)。
上面的例子中整个awk的处理流程:
注:awk是以行为一次处理的单位,而以字段最小的处理单位。
对于上面的案例指令 last -n 5 … 来讲,有几点需要注意的:
注意: awk 后续的所有动作都是以单引号 “’” 括住的,由于单引号与双引号都必须是成对的,所以 awk 的格式内容如查想要以 print 打印时,记得非变量的文字部分,包含一小节 printf 提到的格式中,都需要使用双引号来定义出来,因为单引号已是 awk 的命令固定用法了。
last -n 5 | awk '{print $1 "\t lines: " NR "\t lines: " NR "\t columes: " NF}'
值得关注的是那个等于 “==” 的符号,因为:
cat /etc/passwd | \
awk '{FS=":"} $3 < 10 {print $1 "\t " $3}'
说明:上面的指令运行的效果是查阅第三列小于10以下的数据,并且仅列出账号与第三列。(在 /etc/passwd 当中是以冒号“:”来作为字段的风,该文件中第一字段为账号,第三字段则是UID)
cat /etc/passwd | \
awk 'BEGIN {FS":"} $3 < 10 {print $1 "\t " $3}'
说明:由于案例一中并没有显示出第一行的数据,那么此命令则是把第一行也显示出来了。利用 BEGIN 关键字预先设置 awk 的变量。
此外 awk 还可以进行“计算功能”。
比如有一个文件,内容如下:
name | 1st | 2nd | 3th |
---|---|---|---|
小A | 1000 | 1000 | 1000 |
小B | 2000 | 2000 | 2000 |
小C | 3000 | 3000 | 3000 |
那么怎么计算每个人的总额呢?而且还需要格式化输出,那么可以这样思考:
cat test.txt | \
awk 'NR==1{printf "%10s %10s %10s %10s %10s\n",$1,$2,$3,$4, "Total" }
NR>2{total = $2 + $3 + $4
printf "%10s %10d %10d %10.2f\n", $1, $2, $3, $4, total}'
说明:
原文链接:https://segmentfault.com/a/1190000005720358