awk一个优秀的样式扫描与处理工具,主要用于格式化报文和文本文件中抽取数据包。awk在抽取信息后,才能进行其它文本
操作,完整的awk脚本通常用来格式文本文件的信息。
1.awk的调用方式
awk [-F field-separator] 'commands' fileName
[ - F域分隔符]是可选的,因为a w k使用空格作为缺省的域分隔符,因此如果要浏览域间有空格的文本,不必指定这个选项,
但如果要浏览诸如password文件,此文件各域以冒号作为分隔符,则必须指明- F选项,如:
awk -F: passwed.sh
2.awk的组成
awk有模式和动作组成,在一个awk脚本中可能有许多语句。模式部分决定动作语句何时触发及触发事件。处理即对数据进行
的操作。如果省略模式部分,动作将时刻保持执行状态。模式可以是任何条件语句或复合语句或正则表达式。模式包括两个特殊
字段BEGIN和END。使用BEGIN语句设置计数和打印头。BEGIN语句使用在任何文本浏览动作之前,之后文本浏览动作依据
输入文件开始执行。 END语句用来在awk完成文本浏览动作后打印输出文本总数和结尾状态标志。如果不特别指明模式,awk
总是匹配或打印行数。实际动作在大括号{ }内指明。动作大多数用来打印,但是还有些更长的代码诸如if和循环(looping)语
句及循环退出结构。如果不指明采取动作,awk将打印出所有浏览出来的记录。
注意:BEGIN和END必须大写
3.抽取数据
awk执行时,取浏览域标记标记为$1,$2,$3...$n,如果像打印全部域用$0即可。
例如有以下文本:
[lgm@localhost ~]$ pg text.txt
lby/23/高中
dtt/22/高中
记录的格式为“姓名/年龄/学历”,以“/”为分割符。
1)提取名字和学历
awk -F/ ‘{print $1“/t”$3}’ text.txt
"/t"相当于TAB建
显示结果:
lby 高中
dtt 高中
2) 提取全部信息,并把结果输入道result.txt文件中
awk ‘{print $0}’text.txt > result.txt
上面这种输入方法不会显示在屏幕上,如果既需要显示在屏幕上又要打印到result.txt文件中,可以用以下方法
awk '{print $0}' text.txt | tee result.txt
显示结果为
lby/23/高中
dtt/22/高中
如果你想用" "(或者TAB键)来代替"/"
awk 'gsub("/","/t"){print $0}'
gsub是awk内置的字符串函数
4.awk中正则表达式及操作
1正在表达式
^ --只只匹配行首
$ --只只匹配行尾
* --只一个单字符后紧跟*,匹配0个或多个此单字符
[ ] --只匹配[ ]内字符。可以是一个单字符,也可以是字符序列。可以使用表示[ ]内字符序列范围,如用[ 1 - 5 ]
代替[ 1 2 3 4 5 ]
/ --只用来屏蔽一个元字符的特殊含义。因为有时在shell中一些元字符有特殊含义。/可以使其失去应有意义
. --只匹配任意单字符
pattern / { n / } --只用来匹配前面pattern出现次数。n为次数
pattern / { n,/ } --含义同上,但次数最少为n
pattern / { n,m / } --含义同上,但pattern出现次数在n与m之间
+ --使用+匹配一个或多个字符。
?--匹配模式出现频率。例如使用/X Y?Z/匹配X Y Z或Y Z。
1)匹配
为使一域号匹配正则表达式,使用符号‘~’后紧跟正则表达式,也可以用i f语句。awk中i f后面的条件用()括起来。
例如,找出姓名为“lby”的记录(仍然以text.txt为例):
[lgm@localhost myShell]$ awk '$0~/lby/' text.txt
lby/23/高中
[lgm@localhost myShell]$ awk '{if($0~/lby/) print $1}' text.txt
lby/23/高中
$0~/lby/ 就表示,text.txt文件中的所有域,只要包含"lby"则提取该记录的数据。
2)不匹配
不匹配的符号式‘!~’,用法和匹配模式一样。
[lgm@localhost myShell]$ awk '{if($0!~/lby/) print $1}' text.txt
dtt/22/高中
*只要把正则表达式弄清楚,就可以随便写匹配模式。
1)找出第一个域,值以“t”结尾的记录
[lgm@localhost myShell]$ awk -F/ '{if($1~/t$/) print $0}' text.txt
dtt/22/高中
5.awk内部变量
A R G C --命令行参数个数
A R G V --命令行参数排列
E N V I R O N --支持队列中系统环境变量的使用
FILENAME --a w k浏览的文件名
F N R --浏览文件的记录数
F S --设置输入域分隔符,等价于命令行- F选项
N F --浏览记录的域个数
N R --已读的记录数
O F S --输出域分隔符
O R S --输出记录分隔符
R S --控制记录分隔符
1)输出text.txt文件的记录,及记录个数
awk -F/ 'BEGIN{print "姓名/t年龄/t学历/n"}{print $1"/t"$2"/t"$3} END{print "/n记录个数是:" NR}' text.txt
姓名 年龄 学历
lby 23 高中
dtt 22 高中
记录个数是:2
2)输出text.txt文本包含"lby"字符的记录有多少个域
[lgm@localhost myShell]$ awk -F/ '{if($1~/lby/)print "以/为分割符,域的个数为:"NF}' text.txt
以/为分割符,域的个数为:3
6.awk内部函数
g s u b ( r, s ) --在整个$ 0中用s替代r
g s u b ( r, s , t ) --在整个t中用s替代r
i n d e x ( s , t ) --返回s中字符串t的第一位置
l e n g t h ( s ) --返回s长度
m a t c h ( s , r ) --测试s是否包含匹配r的字符串
s p l i t ( s , a , f s ) --在f s上将s分成序列a
s p r i n t ( f m t , e x p ) --返回经f m t格式化后的e x p
s u b ( r, s ) --用$ 0中最左边最长的子串代替s
s u b s t r ( s , p ) --返回字符串s中从p开始的后缀部分
s u b s t r ( s , p , n ) --返回字符串s中从p开始长度为n的后缀部分
1) s p l i t awk数组
[lgm@localhost ~]$ awk 'BEGIN{print split("1#2#3",myarray,"#") "|" myarray[1],myarray[2],myarray[3]}';
3|1 2 3
使用s p l i t返回字符串数组元素个数。工作方式如下:如果有一字符串,包含一指定分隔 符"#",例如"1#2#3",
将之划分成一个数组。使用s p l i t,指定分隔符及数组名。例中,命令格式为split( "1#2#3",myarray," # ")
,s p l i t然后返回数组下 标数,这里结果为3。