awk笔记
简单的过滤功能
- 搜索带有director的行
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk '/director/ { print }' emp.lst
9876|jai sharma |director |production |12/03/50 |7000
2365|barun sengupta |director |personnel |11/05/47 |4800
1006|channel singhvi |director |sales |03/09/38 |6700
6521|chowdury |director |marketing |26/09/45 |8200
- 以搜索带有符合正则表达式 sa[kx]s*ena 的子串的行
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk '/sa[kx]s*ena/' emp.lst
3212|shyam saksena |d.g.m |account |12/12/55 |6000
2345|j.b. saxena |g.m. |marketing |12/03/45 |8000
把一行拆分成字段
awk命令使用$0表示整行内容,而用$1、$2、$3等表示字段。
awk命令把一串连续的空格符和制表符当作一个分隔符。可以用-F可选项设置分隔符
- 使用-F可选项设置分隔符,打印出每行的第2、3、4、6列的元素
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '/director/{ print $2 $3 $4 $6 }' emp.lst
jai sharma director production 7000
barun sengupta director personnel 4800
channel singhvi director sales 6700
chowdury director marketing 8200
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note#
- 打印第3、4、5行的元素
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" 'NR ==3, NR == 5 { print $2,$3,$4 }' emp.lst
channel singhvi director sales
chowdury director marketing
shyam saksena d.g.m account
- 格式化输出
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" 'NR ==3, NR == 5 { printf ("%s %-10s %-12s %d\n",NR,$2,$3,$6) }' emp.lst
3 channel singhvi director 6700
4 chowdury director 8200
5 shyam saksena d.g.m 6000
- 对输出的行进行排序
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" 'NR ==3, NR == 5 { printf ("%s %-10s %-12s %d\n",NR,$2,$3,$6)|"sort" }' emp.lst
3 channel singhvi director 6700
4 chowdury director 8200
5 shyam saksena d.g.m 6000
- 重定向输出
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" 'NR ==3, NR == 5 { printf ("%s %-10s %-12s %d\n",NR,$2,$3,$6) > "mytext" }' emp.lst
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# ls
emp.lst mytext
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat mytext
3 channel singhvi director 6700
4 chowdury director 8200
5 shyam saksena d.g.m 6000
变量和表达式
awk没有char、int、long、double等数据类型,只把每个表达式理解成一个字符串或一个数值,然后根据上下文进行自动转换
awk允许用户自定义变量,不需要进行类型说明,变量命名区分大小写。
- 定义变量x=5,并用print函数打印,对于emp.lst的每一行,{}中的代码都会执行一次
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk '{ x = "5" ; print x }' emp.lst
5
5
5
5
5
5
- awk没有用于字符串连接的运算符,只要把多个字符串排列在一起,就会自动合并成一个字符串
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk '{ x = "sun" ; y = "com"; print x "." y }' emp.lst
sun.com
sun.com
sun.com
sun.com
sun.com
sun.com
- 字符串和数字的加减法
x = "5"; y = 6 ; z = "A"
print x y # 6转换为字符串,得到56
print x + y # x转化为数字,得到11
print y + z # z转换为数字0,得到6 注:不带数字的字符串转化为数值都会得到0
- 一个表达式的真假值判定方法:一个非空的字符串是真,大于0的数值也是真
if(x) # 只有当x是一个非空字符串或者一个正数才为真
正则表达式
- 寻找第三列符合正则表达式 director * 或等于chairman的行
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '$3 ~ "director.*" || $3 == "chairman" { print $2,$3,$6 }' emp.lst
jai sharma director 7000
barun sengupta director 4800
channel singhvi director 6700
chowdury director 8200
- 寻找第三列不符合正则表达式director*的行
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '$3 !~ "director *" { print $2,$3,$6 }' emp.lst
shyam saksena d.g.m 6000
j.b. saxena g.m. 8000
数值比较
- 寻找出工资大于7500的行
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '$6 > 7500 { printf "%-20s %-12s %d\n", $2, $3, $6 }' emp.lst
chowdury director 8200
j.b. saxena g.m. 8000
- 数值笔记和正则表达式的匹配符
符号 | 含义 |
---|---|
< | 小于 |
<= | 小于等于 |
== | 等于 |
!= | 不等于 |
>= | 大于等于 |
> | 大于 |
~ | 匹配一个正则表达式 |
!~ | 不匹配一个正则表达式 |
数值计算
数值计算支持整数,也支持浮点型,克服了shell不支持浮点数计算的缺点
- 数值计算
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '$3 ~ "director" { printf "%-20s %-12s %d %d %f\n", $2, $3, $6, $6*0.4,$6*0.15 + 3.22 }' emp.lst
jai sharma director 7000 2800 1053.220000
barun sengupta director 4800 1920 723.220000
channel singhvi director 6700 2680 1008.220000
chowdury director 8200 3280 1233.220000
变量
awk允许用户自定义变量
- 利用变量kcount在行前面显示一个序号,初始值默认为0
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" '$3 ~ "director" && $6 > 6700 { kcount = kcount + 1; printf "%3d %-20s %-12s %d\n", kcount,$2,$3,$6 }' emp.lst
1 jai sharma director 7000
2 channel singhvi director 6700
3 chowdury director 8200
运行保存在文件的awk的代码
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat empawk.awk
$3 ~ "director" && $6 > 6700 {
printf "%3d %-20s %-12s %d\n", ++kcount,$2,$3,$6
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" -f empawk.awk emp.lst
1 jai sharma director 7000
2 channel singhvi director 6700
3 chowdury director 8200
BEGIN段和END段
在处理正文前执行BEGIN中的内容,处理正文后执行END中的内容
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat beginEnd.awk
BEGIN {
printf "\t\tEmployee abstract\n\n"
}
$6 > 7500 {
kcount++;
tot+=$6
printf "%3d %-20s %-12s %d\n", kcount,$2,$3,$6
}
END {
printf "\n\t The average basic pay is %6d\n", tot/kcount
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" -f beginEnd.awk emp.lst
Employee abstract
1 chowdury director 8200
2 j.b. saxena g.m. 8000
The average basic pay is 8100
内置变量
变量 | 作用 |
---|---|
NR | 行号 |
FS | 输入字段的分隔符 |
OFS | 输出字段的分隔符 |
NF | 一行内的字段个数 |
FILENAME | 当前输出的文件名 |
ARGC | 命令行的参数个数 |
ARGV | 命令行的参数列表 |
RS | 行分隔符 |
数组
awk的数组和c语言有以下不同:
- 不需要正式定义,数组在使用即被定义
- 数组元素的初始值为0或者字符串,除非被显示地定义
- 数组可以自动扩展
- 索引号几乎可以取任意值,甚至是字符串
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat array.awk
BEGIN {
FS = "|"
printf "%46s\n", "Basic Da Hra Gross"
}
/sales|marketing/ {
da = 0.25 * 6;
hra = 0.5 * $6 ;
gp = $6 + hra + da;
tot[1] += $6;
tot[2] += da;
tot[3] += hra;
tot[4] += gp;
kcount++;
}
END {
printf "\t Average %5d %5d %5d %5d\n", tot[1]/kcount,tot[2]/kcount,tot[3]/kcount,tot[4]/kcount
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" -f array.awk emp.lst
Basic Da Hra Gross
Average 7633 1 3816 11451
-
环境变量数组ENVIRON
保持了全部的环境变量,包括HOME PATH等
函数
awk的内置函数包括:
函数 | 说明 |
---|---|
int(x) | 返回x的整数值 |
sqrt(x) | 返回x的平方根 |
Length | 返回命令行的长度 |
length(x) | 返回x的长度 |
substr(str,m,n) | 返回字符串str中从m开始的, 长度为n的子串 |
index(s1,s2) | 返回字符串s2在字符串s1中的位置 |
split(str,arr,ch) | 按分隔符ch把字符串stg拆分到ch数组中,并返回字段个数 |
system(“cmd”) | 执行UNIX系统命令并返回它的退出状态码 |
if语句
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat if.awk
BEGIN {
print "if else demo"
}
{
if($6 < 6000)
{
da = 0.25 * $6;
}else
{
da = 1000
}
print da
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" -f if.awk emp.lst
if else demo
1000
1200
1000
1000
1000
1000
for循环
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat for.awk
BEGIN{
print "for test\n"
for(key in ENVIRON)
{
print key,ENVIRON[key]
}
print "\n"
}
{
for(k = 1; k<(55- length($0))/2 ; k++)
{
print " "
}
print $0
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -F"|" -f for.awk emp.lst
for test
SSH_CLIENT 223.73.52.13 14438 22
HOME /root
TERM xterm
SHELL /bin/bash
OLDPWD /root/Shells
XDG_RUNTIME_DIR /run/user/0
DISPLAY localhost:22.0
USER root
_ /usr/bin/awk
SHLVL 1
XDG_SESSION_CLASS user
PWD /root/Shells/awk_note
SSH_CONNECTION 223.73.52.13 14438 172.17.25.30 22
LANG en_US.UTF-8
MAIL /var/mail/root
XDG_SESSION_TYPE tty
PATH /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LOGNAME root
SSH_TTY /dev/pts/12
XDG_SESSION_ID 11261
9876|jai sharma |director |production |12/03/50 |7000
2365|barun sengupta |director |personnel |11/05/47 |4800
1006|channel singhvi |director |sales |03/09/38 |6700
6521|chowdury |director |marketing |26/09/45 |8200
3212|shyam saksena |d.g.m |account |12/12/55 |6000
2345|j.b. saxena |g.m. |marketing |12/03/45 |8000
while循环
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# cat while.awk
BEGIN{
i = 0
while(i<10)
{
print i
++i
}
}
root@iZwz9cw7o3sy7zolupfok8Z:~/Shells/awk_note# awk -f while.awk /dev/null
0
1
2
3
4
5
6
7
8
9