awk介绍
1、概述
(1)awk是一种编程语言,主要用于在linux/unix下对文本和数据进行处理,是linux/unix下的一个工具。数据可以来自标准输入、一个或多个文件,或其它命令的输出。
(2)awk的处理文本和数据的方式:逐行扫描文件,默认从第一行到最后一行,寻找匹配的特定模式的行,并在这些行上进行你想要的操作。
(3)awk分别代表其作者姓氏的第一个字母。因为它的作者是三个人,分别是Alfred Aho、Brian Kernighan、Peter Weinberger。
gawk是awk的GNU版本,它提供了Bell实验室和GNU的一些扩展。
(4)下面介绍的awk是以GNU的gawk为例的,在linux系统中已把awk链接到gawk,所以下面全部以awk进行介绍。
2、awk的作用
(1)awk用来处理文件和数据的,是类unix下的一个工具,也是一种编程语言
(2)可以用来统计数据,比如网站的访问量,访问的IP量等等
(3)支持条件判断,支持for和while循环
awk使用方式
1、命令行模式使用
(1)语法结构

awk 选项 '命令部分' 文件名
特别说明:引用shell变量需用双引号引起

(2)常用选项介绍

-F 定义字段分割符号,默认的分隔符是空格    cut -d: -f1
-v 定义变量并赋值

(3)‘命令部分说明’
① 正则表达式,地址定位

'/root/{awk语句}'                sed中: '/root/p'
'NR==1,NR==5{awk语句}'           sed中: '1,5p'
'/^root/,/^ftp/{awk语句}'        sed中:'/^root/,/^ftp/p'

② {awk语句1;awk语句2;…}

'{print $0;print $1}'            sed中:'p'
'NR==5{print $0}'                sed中:'5p'
注:awk命令语句间用分号间隔

③ BEGIN…END…

'BEGIN{awk语句};{处理中};END{awk语句}'
'BEGIN{awk语句};{处理中}'
'{处理中};END{awk语句}'

2、脚本模式使用
(1)脚本编写

#!/bin/awk -f         定义魔法字符
以下是awk引号里的命令清单,不要用引号保护命令,多个命令用分号间隔
BEGIN{FS=":"}
NR==1,NR==3{print $1"\t"$NF}
...

(2)脚本执行

方法1:
awk 选项 -f awk的脚本文件  要处理的文本文件
awk -f awk.sh filename

sed -f sed.sh -i filename

方法2:
./awk的脚本文件(或者绝对路径)    要处理的文本文件
./awk.sh filename

./sed.sh filename

awk内部相关变量

变量变量说明备注
$0当前处理行的所有记录
$1,$2,$3… $n文件中每行以间隔符号分割的不同字段awk -F:‘{print $1,$3}’
NF当前记录的字段数(段数)awk -F:‘print NF’
$NF最后一列$(NF-1)表示倒数第二例
FNR/NR行号
FS定义间隔符,默认空格‘BEGIN{FS=“:”};{print$1,$3}’
OFS定义输出字段分隔符,默认空格‘BEGIN{OFS=“\t”};{print $1,$3}’
RS输入记录分割符,默认换行(行结束判断标志)‘BEGIN{RS=“\T”};{print $0}’
ORS输出记录分割符,默认换行‘BEGIN{ORS=“\n\n”};{print $1,$3}’
FILENAME当前输入的文件名

1、常用内置变量举例

awk -F: '{print $1,$(NF-1)}' 1.txt
awk -F: '{print $1,$(NF-1),$NF,NF}' 1.txt
awk '/root/{print $0}' 1.txt
awk '/root/' 1.txt
awk -F: '/root/{print $1,$NF}' 1.txt 
awk 'NR==1,NR==5' 1.txt 
awk 'NR==1,NR==5{print $0}' 1.txt
awk 'NR==1,NR==5;/^root/{print $0}' 1.txt 

2、内置变量分隔符举例

FS和OFS:
awk 'BEGIN{FS=":"};/^root/,/^lp/{print $1,$NF}' 1.txt
awk -F: 'BEGIN{OFS="\t\t"};/^root/,/^lp/{print $1,$NF}' 1.txt        
root            /bin/bash
bin             /sbin/nologin
daemon          /sbin/nologin
adm             /sbin/nologin
lp              /sbin/nologin
awk -F: 'BEGIN{OFS="@@@"};/^root/,/^lp/{print $1,$NF}' 1.txt     
root@@@/bin/bash
bin@@@/sbin/nologin
daemon@@@/sbin/nologin
adm@@@/sbin/nologin
lp@@@/sbin/nologin
[root@server shell07]# 

RS和ORS:
修改源文件前2行增加制表符和内容:
vim 1.txt
root:x:0:0:root:/root:/bin/bash hello   world
bin:x:1:1:bin:/bin:/sbin/nologin        test1   test2

# awk 'BEGIN{RS="\t"};{print $0}' 1.txt
# awk 'BEGIN{ORS="\t"};{print $0}' 1.txt

awk工作原理

awk -F: '{print $1,$3}' /etc/passwd

1、awk使用一行作为输入,并将这一行赋给内部变量$0,每一行也可称为一个记录,以换行符(RS)结束
2、每行被间隔符:(默认为空格或制表符)分解成字段(或域),每个字段存储在已编号的变量中,从$1开始
问:awk如何知道用空格来分隔字段的呢?

答:因为有一个内部变量FS来确定字段分隔符。初始时,FS赋为空格
3、awk使用print函数打印字段,打印出来的字段会以空格分隔,因为$1,$3之间有一个逗号。逗号比较特殊,它映射为另一个内部变量,称为输出字段分隔符OFS,OFS默认为空格
4、awk处理完一行后,将从文件中获取另一行,并将其存储在$0中,覆盖原来的内容,然后将新的字符串分隔成字段并进行处理。该过程将持续到所有行处理完毕
awk使用进阶
1、格式化输出print和printf

print函数        类似echo "hello world"
# date |awk '{print "Month: "$2 "\nYear: "$NF}'
# awk -F: '{print "username is: " $1 "\t uid is: "$3}' /etc/passwd


printf函数        类似echo -n
# awk -F: '{printf "%-15s %-10s %-15s\n", $1,$2,$3}'  /etc/passwd
# awk -F: '{printf "|%15s| %10s| %15s|\n", $1,$2,$3}' /etc/passwd
# awk -F: '{printf "|%-15s| %-10s| %-15s|\n", $1,$2,$3}' /etc/passwd

awk 'BEGIN{FS=":"};{printf "%-15s %-15s %-15s\n",$1,$6,$NF}' a.txt

%s 字符类型  strings            %-20s
%d 数值类型    
占15字符
- 表示左对齐,默认是右对齐
printf默认不会在行尾自动换行,加\n

2、awk变量定义

# awk -v NUM=3 -F: '{ print $NUM }' /etc/passwd
# awk -v NUM=3 -F: '{ print NUM }' /etc/passwd
# awk -v num=1 'BEGIN{print num}' 
1
# awk -v num=1 'BEGIN{print $num}' 
注意:
awk中调用定义的变量不需要加$

3、awk中BEGIN…END使用
①BEGIN:表示在程序开始前执行
②END :表示所有文件处理完后执行
③用法:‘BEGIN{开始处理之前};{处理中};END{处理结束后}’
4、awk和正则的综合运用

运算符说明
==等于
!=不等于
>大于
<小于
>=大于等于
<=小于等于
~匹配
!~不匹配
!逻辑非
&&逻辑与
\逻辑或

5、awk的脚本编程
(1)流程控制语句
① if结构

if语句:

if [ xxx ];then
xxx
fi

格式:
awk 选项 '正则,地址定位{awk语句}'  文件名

{ if(表达式){语句1;语句2;...}}

awk -F: '{if($3>=500 && $3<=60000) {print $1,$3} }' passwd

# awk -F: '{if($3==0) {print $1"是管理员"} }' passwd 
root是管理员

# awk 'BEGIN{if('$(id -u)'==0) {print "admin"} }'
admin

② if…else结构

if...else语句:
if [ xxx ];then
    xxxxx

else
    xxx
fi

格式:
{if(表达式){语句;语句;...}else{语句;语句;...}}

awk -F: '{ if($3>=500 && $3 != 65534) {print $1"是普通用户"} else {print $1,"不是普通用户"}}' passwd 

awk 'BEGIN{if( '$(id -u)'>=500 && '$(id -u)' !=65534 ) {print "是普通用户"} else {print "不是普通用户"}}'

③ if…elif…else结构

if [xxxx];then
    xxxx
elif [xxx];then
    xxx
....
else
...
fi


if...else if...else语句:

格式:
{ if(表达式1){语句;语句;...}else if(表达式2){语句;语句;...}else if(表达式3){语句;语句;...}else{语句;语句;...}}

(2)循环语句
① for循环

打印1~5
for ((i=1;i<=5;i++));do echo $i;done

# awk 'BEGIN { for(i=1;i<=5;i++) {print i} }'
打印1~10中的奇数
# for ((i=1;i<=10;i+=2));do echo $i;done|awk '{sum+=$0};END{print sum}'
# awk 'BEGIN{ for(i=1;i<=10;i+=2) {print i} }'
# awk 'BEGIN{ for(i=1;i<=10;i+=2) print i }'

计算1-5的和
# awk 'BEGIN{sum=0;for(i=1;i<=5;i++) sum+=i;print sum}'
# awk 'BEGIN{for(i=1;i<=5;i++) (sum+=i);{print sum}}'
# awk 'BEGIN{for(i=1;i<=5;i++) (sum+=i);print sum}'

② while循环

打印1-5
# i=1;while (($i<=5));do echo $i;let i++;done

# awk 'BEGIN { i=1;while(i<=5) {print i;i++} }'
打印1~10中的奇数
# awk 'BEGIN{i=1;while(i<=10) {print i;i+=2} }'
计算1-5的和
# awk 'BEGIN{i=1;sum=0;while(i<=5) {sum+=i;i++}; print sum }'
# awk 'BEGIN {i=1;while(i<=5) {(sum+=i) i++};print sum }'

③ 嵌套循环

嵌套循环:
#!/bin/bash
for ((y=1;y<=5;y++))
do
    for ((x=1;x<=$y;x++))
    do
        echo -n $x    
    done
echo
done

awk 'BEGIN{ for(y=1;y<=5;y++) {for(x=1;x<=y;x++) {printf x} ;print } }'
尝试用三种方法打印99口诀表:
#awk 'BEGIN{for(y=1;y<=9;y++) { for(x=1;x<=y;x++) {printf x"*"y"="x*y"\t"};print} }'

#awk 'BEGIN{for(y=1;y<=9;y++) { for(x=1;x<=y;x++) printf x"*"y"="x*y"\t";print} }'
#awk 'BEGIN{i=1;while(i<=9){for(j=1;j<=i;j++) {printf j"*"i"="j*i"\t"};print;i++ }}'

#awk 'BEGIN{for(i=1;i<=9;i++){j=1;while(j<=i) {printf j"*"i"="i*j"\t";j++};print}}'

循环的控制:
break        条件满足的时候中断循环
continue    条件满足的时候跳过循环

(3)awk算数运算

+ - * / %() ^(幂2^3)
可以在模式中执行计算,awk都将按浮点数方式执行算术运算
# awk 'BEGIN{print 1+1}'
# awk 'BEGIN{print 1**1}'
# awk 'BEGIN{print 2**3}'
# awk 'BEGIN{print 2/3}'
Logo

更多推荐