本文主要介绍 Linux 系统的两个神级工具:sed 和 awk ,他们是Linux高手们必备的技能,很值得咱们去研究的东西。正则表达式
这里是我在网上书上收集的相关资料,由于这两个工具颇有名也很重要,因此这些资料会帮助我更好的了解和熟悉它们。shell
在《sed and awk》一书中(1.2 A Stream Editor)的解释是:编程
Sed本质上是一个编辑器,可是它是非交互式的,这点与VIM不一样;同时它又是面向字符流的,输入的字符流通过Sed的处理后输出。这两个特性使得Sed成为命令行下面很是有用的一个处理工具。bash
Sed自己是一个管道命令,能够分析 standard input 的,主要是用来分析关键字的使用、统计等,此外还能够将数据进行替换、删除、心中、选取特定行等功能。编程语言
sed命令的语法以下所示:编辑器
sed [-nefr] [动做]
参数说明:工具
-n : 使用安静模式,通常全部来自STDIN的数据会被列出到屏幕上,可是 -n 在能够只列出通过 sed 处理过的那一行。测试
-e : 直接在命令行模式上进行 sed 的动做编辑。命令行
-f : 直接将 sed 的动做卸载一个文件内, -f filename 则能够执行 filename 内的 sed 动做。设计
-r : sed 的动做支持的是扩展型正则表达式的语法(默认是基础正则表达式语法)。
-i : 直接修改读取的文件内容,而不是由屏幕输出。
动做说明: [n1],[n2] function
n1,n2:不见得会存在,通常表明选择进行动做的行数。
举例来讲:若是个人动做是须要在 10 到 20 行之间进行的,则“10,20[动做行为]”
function 有下面这些参数:
a:新增,a 的后面能够接字符串,而这些字符串会在新的一行出现(目前的下一行)。
c:替换,c 的后面能够接字符串,这些字符串能够替换n1,n2之间的行!
d:删除,由于是删除,因此 d 后面一般不接任何参数。
i:插入,i 的后面能够接字符串,而这些字符串会在新的一行出现(目前的上一行)。
p:打印,也就是将某个选择的数据打印出来,一般 p 会与参数 sed -n 一块儿运行。
s:替换,能够直接进行替换工做。一般这个 s 的动做能够匹配正则表达式!
例如:1,20s/old/new/g 就是。
以行为单位的新增或删除功能
案例(一)
nl /etc/passwd | sed '2,5d'
说明:
sed 的动做为 '2,5d',那个 d 就是删除,命令运行的效果就是把2~5行给删除。
须要注意的是,本来应该是要执行 sed -e 才对,没有 -e 也行。
另外还须要注意的一点:sed 后面接的动做,请务必要以 '' 两个单引号括住。
若是你只想删除第二行,那么命令就是:nl /etc/passwd | sed '2d'。
若是你想删除第三行到最后一行,那么就能够这么写:nl /etc/passwd | sed '3,$d'
注:$表示最后一行。
案例(二)
nl /etc/passwd | sed '2a drink tea'
说明:
命令执行的效果就是在第二行后面(也就是第三行)加上“drink tea”字样。
若是你想在第二行前面加上字符串,那么你能够这样:nl /etc/passwd | sed '2i drink tea'
注:2a 中的 a 是指第二行后面,而 2i 中的 i 则是指第二行的前面。
案例(三)
nl /etc/passwd | sed '2a drink tea or ......\ drink beer'
说明:
上面的命令的执行效果是在第二行后面加入2行字。
在每一行的后面必需要以反斜杠 来进行新行的增长。
以行为单位的替换与显示功能
案例(一)
nl /etc/passwd | sed '2, 5c No 2-5 number'
说明:
上面的命令的执行效果是将第2~5行的内容替换成“No 2-5 number”
案例(二)
nl /etc/passwd | sed -n '5,7p'
说明:
上面的命令执行的效果是仅列出文件中的第5~7行的内容。
命令中的 -n 表明的是安静模式!可是这个参数建议加上。
案例(三)
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 将test.txt内的每一行结尾为“.” 的换成 !
命令中的 -i 参数可让你的 sed 直接去修改后面接的文件内容,而不是由屏幕输出。
案例(二)
sed -i '$a # This is a test' test.txt
说明:
上面命令执行的效果是利用 sed 直接在test.txt最后一行加入 “This is a test”。
因为 $ 表明的是最后一行,而 a 的操做是新增,所以该文件最后新增。
简单来讲,awk 是一个数据处理工具。
相比于 sed 经常做用于一整行的处理,awk 则比较倾向于将一行分红数个“字段”来处理。所以,awk 至关适合处理小型数据的数据处理。
对于编程语言来说,awk 是一种便于使用且表达能力强的程序设计语言,可应用于各类计算和数据处理任务。
基本语法
awk '条件类型1{动做1} 条件类型2{动做2} ...' filename
awk 后面接两个单引号病加上大括号{}来设置想要对数据进行的处理动做。
awk 能够处理后续接的文件,也能够读取来自签个命令的 standardoutput。
如前面说的,awk 主要是处理每一行的字段内的数据,而默认的字段的分隔符为空格键或者[tab]键。 好比:
last -n 5 // 仅取出登录者的数据前五行(last 能够将登录者的数据取出来)
若是我还要在这些信息中取出:帐号与登录者的IP,且帐号与IP之间以[tab]隔开,那么能够这么改命令:
last -n 5 | awk '{print $1 "\t" $3}'
上面是 awk 最常使用的动做,经过 print 的功能来说字段的数据列出来,字段的分割则以空格键或者[tab]按键来隔开。
上面的例子中,在每一行的每一个字段都是有变量名称的,那就是$1,$2等变量名称。
备注:$1 指的就是第一列,可是 $0 则是表明一整行(第一行)。
上面的例子中整个awk的处理流程:
(1)读入第一行,并将第一行的数据填入$0,$1,$2等变量中; (2)依据条件类型的限制,判断是否须要进行后面的动做; (3)昨晚全部的动做与条件类型; (4)若还有后续的“行”的数据,则重复上面1~3的不知,直到全部的数据都读完为止。
注:awk是以行为一次处理的单位,而以字段最小的处理单位。
对于上面的案例指令 last -n 5 ... 来说,有几点须要注意的:
列出每一行的帐号(就是$1)。
列出目前处理的行数(那就是 awk 内的 NR 变量)。
而且说明,该行有多少个字段(就是 awk 内的 NF 变量)。
注意: awk 后续的全部动做都是以单引号 “'” 括住的,因为单引号与双引号都必须是成对的,因此 awk 的格式内容如查想要以 print 打印时,记得非变量的文字部分,包含一小节 printf 提到的格式中,都须要使用双引号来定义出来,由于单引号已经是 awk 的命令固定用法了。
last -n 5 | awk '{print $1 "\t lines: " NR "\t lines: " NR "\t columes: " NF}'
awk 的运算符
大于: >
小于: <
大于或等于: >=
小于或等于: <=
等于: ==
不等于: !=
值得关注的是那个等于 “==” 的符号,由于:
逻辑运算上面也就是所谓的大于,小于,等于等判断式上面,习惯上是以“==”来表示的。
若是是直接给与一个值,例如变量设置时,就直接使用 = 而已。
案例(一)
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
那么怎么计算每一个人的总额呢?并且还须要格式化输出,那么能够这样思考:
第一行只是说明,因此第一行不要进行加总(NR==1时处理)。
第二行之后就会有加总的状况出现(NR>=2之后处理)。
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}'
说明:
全部 awk 的动做(即在{}内的动做),若是有须要多个命令来辅助是,可利用分号“;”间隔,或者直接以[Enter]按键来隔开每一个命令,上面则是摁了三次。
逻辑运算中,若是是“等于”的状况,则务必使用两个等号“==”!
格式化处输出时,在 printf 的格式设置当中,务必加上 n ,才能实现分行。
与 bash 、shell 的变量不一样,在 awk 当中,变量能够直接使用,不须要加上 $ 符号。