awk 是一个非常棒的数据处理工具!sed 常常用于一整个行的处理, awk 则比较倾向于一行当中分成数个『栏位』(或者称为一个域,也就是一列)来处理。因此,awk 相当的适合处理小型的数据数据处理呢!awk 通常运行的模式是这样的:
awk '条件类型1{动作1} 条件类型2{动作2} ...' filename
awk 后面接两个单引号并加上大括号 {} 来配置想要对数据进行的处理动作。 awk 可以处理后续接的文件,也可以读取来自前个命令的 standard output 。 但如前面说的, awk 主要是处理『每一行的栏位内的数据』,而默认的『栏位的分隔符号为 "空白键" 或 "[tab]键" 』
1、字段分割
awk '{print "first:" $1 "last:" $4} ' forawk
awk -F ":" '{print "user:" $1 "\tshell:" $7}' forawk
-F 参数设置的是 awk 的初始变量 FS,FS 变量控制着 awk 的字段分隔符,默认情况下是空白字符。
2、AWK 代码结构
将 awk 的运行看成 3 部分组成:处理输入前的初始化,处理输入过程,处理完所有输入后的扫尾工作。BEGIN 和 END 分别映射到第一部分和第三部分。
(1) BEGIN 代码快
awk 脚本包含一个BEGIN 代码快, 格式是 BEGIN 标签加上{}。 当脚本很简单时,使用-F 参数能减少输入的字符数,但是,当脚本很复杂时,使用 FS 参数清晰的
显示了 awk 的逻辑。
awk 'BEGIN{FS=":"}{print "user:" $1 "\tshell" $7}' forsed
(2)END 代码快
[root@forshell shell]# cat end
BEGIN{print "how many people with nologin?"}
/nologin/{++adder}
END{print "'nologin' appears "adder" times"}
写在 BEGIN 代码块中的代码只在初始化时被运行一次,与正则表达式匹配,成功,执行++adder
[root@forshell shell]# awk -f end /etc/passwd
how many people with nologin?
'nologin' appears 25 times
[root@forshell shell]# grep -c nologin /etc/passwd
25
(3) 模式匹配
/正则表达式/ {匹配后执行的操作}
[root@forshell shell]# awk -F ":" '/bin\/bash/ {print "hello," $1}' /etc/passwd
hello,root #匹配/bin/bash
hello,pop
hello,ling
awk 'BEGIN{FS=":"} /bin\/bash/ {print "hello," $1}' /etc/passwd
3、变量
变量使用无需先声明,变量只存储字符串,当需要时在转换为其他类型大小写敏感。局部变量小写,全局变量带一个字母大写,内建变量全部大写。
常用的内建变量:
FS:字段分割符,默认为空格 RS:输出记录分割字符
OFS:输出字段分割字符 ORS:输出记录分割字符,默认为“\n”
NR:在工作中的记录数 FNR:当前输入文件的记录数
NF:当前记录的字段数
4、格式化输出
Print:打印整行,输出到 stdout
Printf :将格式化字符串打印到 stdout,类似于C语言中的printf
Sprintf :返回可以赋值给变量的格式化字符串
# echo "65" | awk '{printf "%c\n",$0}'
A
5、字符串函数
(1)子字符串查找
index(str,substr) :返回子串在整个串中第一次出现的位置。函数字符串开始位置为 1,没有找到子串返回 0.
(2)子字符串提取
substr(str,position,[length]):返回 str 中从 position开始的 length 个字符
[root@forshell shell]# cat info.txt
029-587-49079:Lily
029-587-49081:Kathy
[root@forshell shell]# awk '{print substr($1,5,9)}' info.txt
587-49079
587-49081
(3)字符串匹配
match(str,/reg/):如果在串 str 中找到正则/reg/匹配的串,则返回出现的位置,未找到则返回 0。
与 index()的区别:index()函数是查找固定字符串的位置,match()支持正则表达式查询。
(4)子字符串替换
sub(/reg/,replacement,target):只替换第一个匹配字符串。与正则表达式/reg/进行匹配,将 target 中左边最长的匹配部分替换成 replacement。如果没有给定 target,则默认使用整条记录。
gsub(/reg/,replacement,target):替换所有匹配的字符串。
# echo "testthisistest test"|awk '{gsub(/test/,"mytest");print}'
mytestthisismytest mytest
#echo "testthisistest test"|awk '{sub(/test/,"mytest");print}'
mytestthisistest test
(5)大小写转换
toupper(str):对字符串进行大小写转换
tolower(str):对字符串进行大小写转换
(6)其他内建函数
blength[([s])] 计算字符串长度(byte为单位)
length[([s])] 计算字符串长度(character为单位)
rand() 生成随机数
srand([expr]) 设置rand() seed
int(x) 字符串转换为整型
split(s, a[, fs]) 将字符串分割到数组中
-
awk 的命令间隔:所有 awk 的动作,亦即在 {} 内的动作,如果有需要多个命令辅助时,可利用分号『;』间隔
-
逻辑运算当中,如果是『等於』的情况,则务必使用两个等号『==』!
-
格式化输出时,在 printf 的格式配置当中,务必加上 \n ,才能进行分行!
-
与 bash shell 的变量不同,在 awk 当中,变量可以直接使用,不需加上 $ 符号。
6、实例
AWK脚本文件开头需要注明调用方式,典型写法为:
#!/bin/awk -f
注意-f后面有空格。
脚本文件需要有执行权限,如果没有需要使用chmod +x progfile赋权。
(1)显示文件中包含tom的匹配行
# awk '/tom/' file
(2)显示/etc/passwd文件中的UID大于500的所有用户的用户名和登录shell
# awk -F : '$3<10 {print $1","$7}' /etc/passwd
(3)为使一域匹配正则表达式,使用符合‘~’后紧跟正则表达式。也可以if语句,awk中if后面的条件用()括起来。
‘或’匹配,使用‘|’,需要使用括号括起来
awk '$0 ~ /(yellow|green)/' file
(4)下面脚本先将"123#456#789" 使用split环峰,再循环打印个数组元素
#!/bin/awk -f
#name: arraytest.awk
#prints out an array
BEGIN{
record="123#456#789";
split(record,myarray,"#")
}
END{
for ( i in myarray )
{
print myarray[i]
}
}
阅读(2091) | 评论(0) | 转发(0) |