awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入、一个或多个文件,或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。
awk的处理文本和数据的方式是这样的,它逐行扫描文件,从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。如果没有指定处理动作,则把匹配的行显示到标准输出(屏幕),如果没有指定模式,则所有被操作所指定的行都被处理。
一般语法格式
1.# awk '{ print }' /etc/passwd
或# awk '{ print $0 }' /etc/passwd
马上显示/etc/passwd的内容,其中$0变量表示整个当前行
2.# awk '{ print "william" }' /etc/passwd
或# awk '{ print "" }' /etc/passwd
第一条按照/etc/passwd文件中的行数显示william,第二条则显示空行。
字段
3.# awk -F: '{ print $1 }' /etc/passwd
或# awk -F: '{ print $1 $3 }' /etc/passwd
第一条打印输入文件中每一行中出现的第一个字段,第二条则打印第一和第三字段。其中-F:表示指定“:”作为字段分隔符。
4.# awk -F: '{ print $1 " " $3 }' /etc/passwd
# awk -F: '{ print "username: "$1 "\t\tuid: " $3 }' /etc/passwd
例3中输出的结果两个字段之间没有空格,这第一条命令就是加空格,第二条则加了文本标签。
外部脚本
5.# awk -f my.awk /etc/passwd
如果要运行外部的脚本加上-f选项即可,其中my.awk是脚本,/etc/passwd是要操作的文本。
BEGIN和END块
6.BEGIN{
FS=":" 相当于命令行中的-F:
}
{ print $1 }
END{
print "william"
}
awk开始处理文件之前会执行BEGIN块,awk处理文件之后会执行END块。
表达式和块
7.# awk '/root/ { print }' /etc/passwd 打印包含root的行
# awk '/^root/ { print }' /etc/passwd 打印以root开头的行
# awk '/~root/ { print NR NF }' /etc/passwd 有以root结尾的行打印当前记录数和当前记录字段数
# awk '/^root|wang/ { print }' /etc/passwd 打印以root或wang开头的行
# awk '/^[rw]/ { print }' /etc/passwd 打印以字母r或w开头的行
# awk '$1 ~/[0-9]/ { print }' /etc/passwd 打印字段1中以数字结尾的行
# awk -F: '$4 ^/[0-9]/ { print }' /etc/passwd 打印字段4中以数字开头的行
8.# awk -F: '$4==27 { print }' /etc/passwd 打印字段4等于27的行
# awk -F: '$4!=27 || $3>492 { print }' /etc/passwd 打印字段4不等于27或字段3大于492的行
# awk -F: '$4==27 || $3>42 { print $1+10 }' /etc/passwd 假如字段4等于27或者字段3大于42,打印$1+10的值,如果$1不是数字默认为0。
# awk -F: '{print $4==27 ? "ok" : "err"}' /etc/passwd 字段4等于27打印ok,否则打印err
# awk '/^root/,/^bin/' /etc/passwd 打印以root开头到以bin开头的所有行,假如出现第二个以root开头的行,则到下一个yibin开头的行结束或到文件结尾。
条件语句
9.BEGIN{
FS=":"
}
{
if($3==27){
if($4==27){
print "love"
}
}
else if($1 ~/root/) { print "one"} //~是包含,^是不包含
else {
print "others" " " $1}
}
END{
print "william"
}
变量
10.BEGIN {x=0}
/^$/ {x=x+1}
END {print "There are "x" blank lines."}
计算空白行的数量
11.# awk -f my.awk x=8 ./test.c
原来是5,加入x=8后,结果变成了13.另外BEGIN {x=0}可以不要。
12.BEGIN {x="0.01"} //注意变成字符串了
/^$/ {x=x+1}
END {print "There are "x" blank lines."}
执行# awk -f my.awk ./test.c 结果是5.01
字段分隔符
前面设置FS=":",当然也可以设置多个任意字符为分隔符。
例如:
FS="\t+" +号表示一个或多个
FS="root[0-9][0-9]" 表示root后面接两个数字为分隔符
记录分隔符
NR 记录号 NS 记录分隔符 FS字段分隔符
比如通讯录把名字 地址 电话号码整理为一个记录。其中文本如下
wang
Hunan Chenzhou
123456
li
Guangzhou Zhuhai
654321
13.执行脚本为:BEGIN {
FS="\n"
RS=""
}
{print $1 ","$2","$3}
输出:
wang,Hunan Chenzhou,123456
li,Guangzhou Zhuhai,654321
14.执行脚本为:BEGIN {
FS="\n"
RS=""
OFS="-" 输出字段间隔
ORS="\nnext:\n" 输出记录间隔
}
{print $1, $2, $3}
输出:
wang-Hunan Chenzhou-123456
next:
li-Guangzhou Zhuhai-654321
next:
循环语句
15.BEGIN {
FS="\n"
RS=""
OFS="-"
ORS=""
}
{
x=1
while(x<NF){
print $x "\t" 上面的OFS赋值将不起作用
x++
}
print $NF "\n"}
此外有do while,for,break,continue。
数组
16.
数组下标经常从1开始,而不是0
数组下标字符串化 例如:myarr["name"]="wang" 就算不是字符串也会被看成字符串。
17.delete myarr[1] 删除数组元素1
18.if (wang in myarr) {print "ok"} 查看数组元素
字符串函数
string="Wo men shi ku bi de cheng xu yuan !"
print string[2] 会报错!!
怎么办?
print length(string) 打印字符串长度
print index(string,"men") 查找men在字符串中的位置
print tolower(string) 转换为小写
print toupper(string) 转换为大写
mysbu=substr(string,startpos,maxlen) 在startpos开始截取maxlen这么长的字符
print match(string,/men/),RSTART,RLENGTH 寻找匹配men的位子和长度
sbu(old,new,string) 替换一个
gsbu(old,new,string) 全部替换
num=split("1,2,3,4,5,6",mynum,",") 切开字符串,并将各部分放到整数下标的数组中
函数格式
function 函数名(参数)
{
……
}