目录
62. 变量
64. 算术操作符
65. 字符串操作符
66. 赋值操作符
67. 比较操作符
68. 正则表达式操作符
62. 变量
Awk 变量以字母开头,后续字符可以是数字、字母、或下划线。关键字不能用作 awk 变量。
不像其他编程语言, awk 变量可以直接使用而不需事先声明。如果要初始化变量,最好在
BEGIN 区域内作,它只会执行一次。
Awk 中没有数据类型的概念,一个 awk 变量是 number 还是 string 取决于该变量所处的上下
文。
employee-sal.txt 示例文件
emploeyee-sal.txt 以逗号作为字段分隔符,包含五个雇员的信息,格式如下 :
employee-numer,employee-name,employee-title,salary
创建下面文件 :
$ vi employee-sal.txt
101,John Doe,CEO,10000
102,Jason Smith,IT Manager,5000
103,Raj Reddy,Sysadmin,4500
104,Anand Ram,Developer,4500
105,Jane Miller,Sales Manager,3000
下面的例子将教你如何在 awk 中创建和使用自己的变量,该例中, ”total” 便是用户建立的用
来存储公司所有雇员工资总和的变量。
$ vi total-company-salary.awk
BEGIN {
FS=",";
total=0;
}
{
print $2 "'s slary is: " $4;
total=total+$4
}
END {
print "---\nTotal company salary =$"total;
}
$ awk -f total-company-salary.awk employee-sal.txt
John Doe's slary is: 10000
Jason Smith's slary is: 5000
Raj Reddy's slary is: 4500Anand Ram's slary is: 4500
Jane Miller's slary is: 3000
---
Total company salary =$27000
63. 一元操作符
只接受单个操作数的操作符叫做一元操作符。
下面的例子使用取反操作 :
$ awk -F, '{print -$4}' employee-sal.txt
-10000
-5000
-4500
-4500
-3000
下面的例子演示取正、取反操作符对文件中存放的复数的作用:
$ vi negative.txt
-1
-2
-3
$ awk '{print +$1}' negative.txt
-1
-2
-3
$ awk '{print -$1}' negative.txt
1
2
3
自增和自减操作
自增和自减改变变量的值,它可以在使用变量“之前”或“之后”改变变量的值。在表达式
中,使用的可能是改变前的值 (post) 或改变后的值 (pre). 使用改变后的变量值 (pre) 即是在变量前面加上 ++( 或 --) ,首先把变量的值加 1( 或减 1) ,然后
把改变后的值应用到表达式的其它操作中。
使用改变前的变量值 (post) 即是在变量后面加上 ++( 或 --) ,首先把变量值应用到表达式中进行
计算,然后把变量的值加 1( 或减 1) 。
Pre 自增示例 :
$ awk -F, '{print ++$4}' employee-sal.txt
10001
5001
4501
4501
3001
Pre 自减示例 :
$ awk -F, '{print --$4}' employee-sal.txt
9999
4999
4499
4499
2999
Post 自增示例 :
( 因为 ++ 在 print 语句中,所以变量的原始值被打印 )
$ awk -F, '{print $4++}' employee-sal.txt
10000
5000
4500
4500
3000
Post 自减示例 :
( 因为 ++ 是单独语句,所以自增后的值被打印 )
$ awk -F, '{$4++;print $4}' employee-sal.txt
10001
5001
4501
4501
3001
Post 自减示例 :
( 因为 — 在 print 语句中,所以变量原始值被打印 )
$ awk -F, '{print $4--}' employee-sal.txt
10000
5000
4500
4500
3000
Post 自减示例 :
( 因为 — 在单独语句中,所以自减后的值被打印 )
$ awk -F, '{$4--;print $4}' employee-sal.txt
9999
4999
4499
4499
2999
下面是一个有用的例子,显示所有登录到 shell 的用户数,即哪些用户可以登录 shell 并获得
命令提示符。
使用算后自增运算符 ( 尽管变量值只到 END 区域才打印出来,算前自增仍会产生同
样的结果 )
脚本的 body 区域包含一个模式匹配,因此只有最后一个字段匹配模式 /bin/bash 时,
body 的代码才会执行
提示 : 正则表达式应该包含在 // 之间,但如果正则表达式中的 / 必须转移,以避免被
解析为正则表达式的结尾
当有匹配到模式的行时,变量 n 的值增加 1 ,最终的值在 END 区域打印出来。
打印所有可登陆 shell 的用户总数 :
$ awk -F':' '$NF ~ /\/bin\/bash/ { n++ }; END { print n }' /etc/passwd
2
64. 算术操作符
需要两个操作数的操作符,成为二元操作符。 Awk 中有多种基本二元操作符 ( 如算术操作符、
字符串操作符、赋值操作符,等等 ) 。
下面是算术运算操作符 :
下面的例子展示 +,-,*,/ 的用法 . 下面例子完成两个事情 :
1. 将每件单独的商品价格减少 20%
2. 将每件单独的商品的数量减少 1
创建并运行 awk 算术运算脚本 :
$ vi arithmetic.awk
BEGIN {
FS=",";
OFS=",";
item_discount=0;
}
{
item_discount=$4*20/100;
print $1,$2,$3,$4-item_discount,$5-1;
}
$ awk -f arithmetic.awk items.txt
101,HD Camcorder,Video,168,9
102,Refrigerator,appliance,680,1
103,MP3 Player,Audio,216,14
104,Tennis Racket,Sports,152,19
105,Laser Printer,Office,380,4
下面的例子只打印偶数行。打印前会检查行号是否能被 2 整除,如果整除,则执行默认的操
作 ( 打印整行 ).
取模运算演示 :
$ awk 'NR % 2 == 0' items.txt
102,Refrigerator,appliance,850,2
104,Tennis Racket,Sports,190,20
65. 字符串操作符
( 空格 ) 是连接字符串的操作符。
下面例子中,有三处使用了字符串连接。在语句 ”string3=string1 string2” 中, string3 包含了
string1 和 string2 连接后的内容。每个 print 语句都把一个静态字符串和 awk 变量做了连接。
ᨀ示 : 这个操作符解释了为什么在打印多个变量时,如果要使用 OFS 分隔每个字段,就需要
在 print 语句中用逗号分隔每个变量。如果没有使用逗号分隔,那么会把所有值连接成一个
字符串。 $ cat string.awk
BEGIN {
FS=",";
OFS=",";
string1="Audio";
string2="Video";
numberstring="100";
string3=string1 string2;
print "Concatenate string is:" string3;
numberstring=numberstring+1;
print "String to number:" numberstring;
}
$ awk -f string.awk items.txt
Concatenate string is:AudioVideo
String to number:101
66. 赋值操作符
与其他大部分编程语言一样, awk 使用 = 作为赋值操作符。和 C 语言一样, awk 支持赋值
的缩写方式。
下面的例子演示如何使用赋值 :
$ cat assignment.awk
BEGIN {
FS=",";
OFS=",";
total1 = total2 = total3 = total4 = total5 = 10;
total1 += 5; print total1;
total2 -= 5; print total2;
total3 *= 5; print total3;
total4 /= 5; print total4;
total5 %= 5; print total5;
} $ awk -f assignment.awk
15
5
50
2
0
下面的例子使用加法赋值的缩写形式 .
显示所有商品的清单:
$ awk -F ',' 'BEGIN { total=0 } { total += $5 } END {print "Total Quantity: " total }' items.txt
Total Quantity: 52
下面的例子统计输入文件中所有的字段数。 Awk 读取每一行,并把字段数量增加到变量 total
中。然后在 END 区域打印该变量。
$ awk -F ',' 'BEGIN { total = 0 } { total += NF } END { print total }' items.txt
25
67. 比较操作符
提示:下面的例子,如果不指定操作, awk 会打印符合条件的整条记录。
打印数量小于等于临界值 5 的商品信息:
$ awk -F ',' '$5 <= 5' items.txt
102,Refrigerator,appliance,850,2
105,Laser Printer,Office,475,5
打印编号为 103 的商品信息:
$ awk -F "," '$1 == 103' items.txt
103,MP3 Player,Audio,270,15
提示 : 不要把 ==( 等于 ) 和 =( 赋值 ) 搞混了。
打印编号为 103 的商品的描述信息 :
$ awk -F "," '$1 == 103 { print $2}' items.txt
MP3 Player
打印除 Video 以外的所有商品:
$ awk -F "," '$3 != "Video"' items.txt
102,Refrigerator,appliance,850,2
103,MP3 Player,Audio,270,15
104,Tennis Racket,Sports,190,20
105,Laser Printer,Office,475,5
和上面相同,但只打印商品描述信息:
$ awk -F "," '$3 != "Video" { print $2}' items.txt
Refrigerator
MP3 Player
Tennis Racket
Laser Printer
使用&&比较两个条件,打印价钱低于 900 并且数量小于等于临界值 5 的商品信息:
$ awk -F "," '$4 < 900 && $5 <= 5' items.txt
102,Refrigerator,appliance,850,2
105,Laser Printer,Office,475,5
和上面相同,但只打印商品描述信息:
$ awk -F "," '$4 < 900 && $5 <= 5 {print $2}' items.txt
Refrigerator
Laser Printer
使用||比较两个条件,打印价钱低于 900 或者数量小于等于临界值 5 的商品信息:
$ awk -F "," '$4 < 900 || $5 <= 5' items.txt
101,HD Camcorder,Video,210,10
102,Refrigerator,appliance,850,2
103,MP3 Player,Audio,270,15
104,Tennis Racket,Sports,190,20
105,Laser Printer,Office,475,
和上面相同,但只打印商品描述信息:
$ awk -F "," '$4 < 900 || $5 <= 5 {print $2}' items.txt
HD Camcorder
Refrigerator
MP3 Player
Tennis Racket
Laser Printer 下面例子使用 > 条件,打印 /etc/password 中最大的 UID( 以及其所在的整行 ) 。 Awk 把最大的
UID( 第 3 个字段 ) 放在变量 maxuid 中,并且把包含最大 UID 的行复制到变量 maxline 中。循
环执行完后,打印最大的 UID 和其所在的行。
$ awk -F ':' '$3 > maxuid { maxuid = $3; maxline = $0 } END { print maxuid,maxline }' /etc/passwd
65534 nobody:x:65534:65533:nobody:/var/lib/nobody:/bin/bash
打印/etc/passwd 中 UID 和 GROUP ID 相同的用户信息
$ awk -F ':' '$3 == $4' /etc/passwd
root:x:0:0:root:/root:/bin/bash
打印/etc/passwd 中 UID >= 100 并且用户的 shell 是/bin/sh 的用户:
$ awk -F ':' '$3 >= 100 && $NF ~ /\/bin\/sh/ ' /etc/passwd
mygame:x:2300:0::/opt/game:/bin/sh
打印 /etc/passwd 中没有注释信息 ( 第 5 个字段 ) 的用户 :
mkey3g@mkey:/opt/mkey3g/ec> awk -F ':' '$5 == ""' /etc/passwd
mfs:x:2001:1000::/home/mfs:/bin/nologin
68. 正则表达式操作符
使用 == 时, awk 检查精确匹配。 下面的例子不会打印任何信息,因为 items.txt 中,没有任
何一条记录的第二个字段精确匹配关键字 ”Tennis”,”Tennis Racket” 不是精确匹配。
打印第二个字段为 ”Tennis” 的记录 :
$ awk -F "," '$2 == "Tennis"' items.txt
当使用 ~ 时, awk 执行模糊匹配,检索 ” 包含 ” 关键字的记录 .
打印第二个字段包含 ”Tennis” 的行 :
$ awk -F "," '$2 ~ "Tennis"' items.txt
104,Tennis Racket,Sports,190,20
!~ 对应 ~, 即不匹配 .
打印第二个字段不包含 ”Tennis” 的行 :
$ awk -F "," '$2 !~ "Tennis"' items.txt
101,HD Camcorder,Video,210,10
102,Refrigerator,appliance,850,2
103,MP3 Player,Audio,270,15
105,Laser Printer,Office,475,5
下面的例子打印 shell 为 /bin/bash 的用户的总数,如果最后一个字段包含 ”/bin/bash”, 则变量
n 增加 1
$ awk -F ':' '$NF ~ /\/bin\/bash/ { n++ } END { print n }' /etc/passwd
13
资料来源于《SedandAwk101Hacks》,大家有兴趣可以买一本,也可以关注我,我更新完它。
曾经,我花费大半月将它们跑完,现在啥都忘了,还是要常用。
只为学习交流,不为获利,侵权联系立删。