sed与awk-第十三章-附录2awk快速参考
附录二 awk的快速参考
命令行语法
awk两种调用形式
选项说明
| 选项 | 说明 |
|---|---|
-v var=value |
在BEGIN执行之前就设置变量,BEGIN块内可以使用 |
-F re |
设置字段分隔符FS为正则re |
-- |
标记选项结束;用于文件名以-开头,防止被识别为命令行选项 |
注意:命令行直接写
var=value这种赋值,要等到读取第一条输入记录之后才生效,BEGIN块中访问不到。想要BEGIN可用,必须用‑v。
不提供输入文件,或者文件名写‑,代表从标准输入读取。
用shell实现调用awk
- 单行简单脚本直接终端敲;复用脚本放到shell文件,
chmod +x赋予执行权限。 #!自执行awk脚本头(现代UNIX/Linux)
注意路径
/usr/bin/awk视系统不同可能变化;‑f不能省略。
脚本执行时,命令行传入的参数、文件名直接交给awk处理。
awk语言概要
记录和字段
- 记录(record):默认一行就是一条记录;由RS记录分隔符控制。
- 字段(field):一条记录被FS切分成多个字段。
$0:整条原始记录$1、$2…:第1、第2个字段$NF:最后一个字段
示例,打印每行第一个字段:
|
|
修改字段分隔符两种写法:
设置空行作为记录分隔符(RS="",段落为一条记录),每行作为一个字段:
|
|
注意:
RS=""(空字符串,按空行分割段落)时,换行符永远作为字段分隔。
脚本的格式
awk脚本由多条规则组成:
|
|
- 没有pattern:action对所有行执行。
|
|
- 只有pattern,没有{action}:默认动作等价
print,匹配就打印该行。 - 支持自定义函数
调用函数时,函数名和左括号之间不能有空格;定义函数的时候可以有空格。
行的终止
- 语句分隔:换行 或者
;分号;分号可以把多条语句写同一行,降低可读性。 - if、for、while后面多条语句必须用大括号包裹,单条语句可以不写大括号。
- 代码换行续行:反斜杠
\放在行尾;也可以在,{&&||后面直接换行;gawk额外支持?:续行。
标准awk字符串不能跨行;gawk中字符串末尾加
\可以换行。
注释
# 开始,到本行行尾结束;不能用反斜杠延续到下一行。
模式
模式可以是下面任意一种:
/正则表达式/- 关系表达式
$1 > 100 BEGIN、ENDpattern1 , pattern2地址范围(从匹配1到匹配2,中间全部记录)
!放在模式前面:取反,匹配不满足条件的记录。- 组合:
&&逻辑与、||逻辑或;可以用括号改变优先级。 BEGIN:读取第一条输入之前执行;END:全部输入处理完毕之后执行。
多个BEGIN、END会被awk自动合并成一个执行。
正则表达式 表B‑1
优先级从高到低
| 特殊字符 | 作用 |
|---|---|
| 普通字符c | 匹配字面c |
\ |
转义元字符 |
^ |
字符串开头 |
$ |
字符串末尾 |
. |
任意单个字符(包含换行) |
[...] |
字符集;^放开头取反;‑表示范围;]放第一位代表字面右方括号 |
r1|r2 |
匹配r1或者r2 |
(r1)(r2) |
正则拼接,先后匹配 |
r* |
前面r出现0次或多次 |
r+ |
前面r出现1次或多次 |
r? |
前面r出现0次或1次 |
(r) |
分组 |
^与$针对整个字符串,不会匹配字符串内部嵌入的换行。
POSIX字符类 表B‑2
写在[[:...:]]内部,可移植,推荐处理多国语言。
| 符号 | 含义 |
|---|---|
[:alnum:] |
字母数字 |
[:alpha:] |
字母 |
[:blank:] |
空格、制表符 |
[:cntrl:] |
控制字符 |
[:digit:] |
数字0‑9 |
[:graph:] |
可见非空白字符 |
[:lower:] |
小写字母 |
[:print:] |
全部可打印字符 |
[:punct:] |
标点符号 |
[:space:] |
全部空白 |
[:upper:] |
大写字母 |
[:xdigit:] |
十六进制数字 |
[.symbol.]排序符号、[=equiv=]等价字符类,实际很少使用。
表达式
常量分为字符串常量(双引号包裹)、数字常量(不加引号)。
转义序列 表B‑3
| 序列 | 说明 |
|---|---|
\a |
蜂鸣报警BEL |
\b |
退格 |
\f |
换页 |
\n |
换行 |
\r |
回车 |
\t |
水平制表 |
\v |
垂直制表 |
\ddd |
八进制字符 1‑3位数字 |
\xhh |
十六进制(gawk扩展,非POSIX标准) |
变量
三类变量:自定义变量、内置系统变量(大写)、字段变量$n。
- 变量命名:字母数字下划线,不能数字开头;大小写敏感。
- 不需要提前声明;未初始化变量:字符串值是空串
"",数值是0。awk根据上下文自动决定当作字符串或者数字。 - 赋值:
var = expr - 字段:
$0完整记录;$1…$NF;$NF取最后一个字段。
数组
awk全部是关联数组(哈希):下标可以是数字,也可以是字符串;不保证存储顺序。
gawk/mawk扩展支持
delete arr直接清空整个数组,不属于POSIX标准。
系统变量 表B‑4
| 变量 | 说明 | 默认值 |
|---|---|---|
ARGC |
命令行参数总个数 | |
ARGV |
命令行参数数组,ARGV[0]是程序名 | |
CONVFMT |
数字转字符串格式 | %.6g POSIX |
ENVIRON |
环境变量关联数组,ENVIRON["HOME"]取环境变量 |
|
FILENAME |
当前正在处理的输入文件名 | |
FNR |
当前文件内部记录号,换文件重置为1 | |
FS |
输入字段分隔符 | 空格 |
NF |
当前记录字段数量 | |
NR |
全局记录号,跨文件持续累加 | |
OFMT |
数字print输出格式 | %.6g |
OFS |
输出字段分隔符,print逗号输出时字段之间的分隔 | 空格 |
ORS |
输出记录分隔符,每条print末尾追加 | \n |
RSTART |
match()匹配内容起始下标 | |
RLENGTH |
match()匹配到的字符串长度 | |
RS |
输入记录分隔符;空串代表按空行分段落 | \n |
SUBSEP |
多维模拟数组下标连接字符,arr[a,b]内部使用 |
\034 |
操作符(按优先级从高到低)表B‑5
| 操作符 | 功能 |
|---|---|
$ |
字段引用 $1 $NF |
++ -- |
自增、自减(前缀后缀) |
! + - |
逻辑非、正号、负号 |
* / % |
乘、除、取模 |
+ - |
加、减 |
| (字符串拼接) | 没有符号,直接写变量挨着 |
< <= > >= != == |
比较 |
~ !~ |
正则匹配、不匹配 |
&& |
逻辑与 |
|| |
逻辑或 |
?: |
三元条件表达式 |
= += -= *= /= %= |
赋值 |
**求幂运算符属于扩展,不是POSIX标准awk。
语句和内置函数汇总
区分:函数有返回值;
getline是函数但是不加括号;print/printf属于语句。
| 名称 | 简要说明 |
|---|---|
atan2(y,x) |
返回y/x的反正切,弧度 |
break |
跳出for/while/do‑while循环 |
close(expr) |
关闭已经打开的文件或者管道;字符串必须和打开时完全一致,包含空格 |
continue |
直接进入循环下一轮迭代 |
cos(x) |
余弦,参数弧度 |
delete arr[idx] |
删除数组单个元素 |
do{...}while(expr) |
先执行循环体,再判断条件 |
exit [n] |
退出脚本;END块仍然会执行;n设置返回码 |
exp(x) |
e的x次方 |
for(init;cond;inc) stmt |
C风格for循环 |
for(idx in arr) stmt |
遍历关联数组下标 |
getline |
读取一行;返回1成功,0 EOF,‑1错误。 getline;getline var;getline < file;`cmd |
gsub(r,s,[t]) |
全局替换;返回替换次数;t省略默认$0 |
if(cond) stmt [else stmt] |
条件判断 |
index(s,t) |
返回子串t在s中的位置,从1开始,找不到返回0 |
int(x) |
截断取整数,丢弃小数部分 |
length([s]) |
返回字符串长度;无参数取$0 |
log(x) |
自然对数 |
match(s,r) |
在s匹配正则r;设置RSTART、RLENGTH;匹配不到返回0 |
next |
读取下一条记录,回到脚本开头重新执行规则 |
print exprlist [ > file >> file cmd ] |
输出;>覆盖;>>追加;输出到管道命令 |
printf(fmt,args) [重定向] |
格式化输出,不会自动加换行 |
rand() |
返回 [0,1) 的随机浮点数;每次运行默认序列相同 |
sin(x) |
正弦,弧度 |
split(str,arr,sep) |
将字符串按照sep切分存入数组arr;sep省略使用FS;返回元素个数 |
sprintf(fmt,args) |
返回格式化后的字符串,不打印输出 |
sqrt(x) |
平方根 |
srand([seed]) |
设置随机数种子;不带参数使用当前时间;返回旧种子 |
sub(r,s,[t]) |
单次替换,只替换第一个匹配;返回1成功,0失败;t省略取$0 |
substr(s,begin,[len]) |
截取子串;起始位置从1开始;len省略取后面全部字符 |
system(cmd) |
执行shell命令;返回退出状态;拿不到命令输出,要用cmd|getline |
tolower(s) |
全部转小写,返回新字符串 |
toupper(s) |
全部转大写,返回新字符串 |
while(cond) stmt |
while循环 |
printf / sprintf 格式说明 表B‑6
格式模板:%[‑][宽度][.精度]格式符
-:左对齐;不写默认右对齐。- 宽度:最小输出字符宽度;不足补空格。
.精度:浮点数小数点位数;字符串最多输出多少字符。- 可以用
*动态传入宽度和精度。
|
|
| 格式符 | 说明 |
|---|---|
c |
输出单个ASCII字符 |
d / i |
十进制整数 |
e E |
科学计数法 |
f |
浮点数 |
g G |
自动选择e/f,去除末尾多余0 |
o |
八进制 |
s |
字符串 |
x X |
十六进制 |
%% |
输出字面百分号% |
注意:C库的sprintf是无偏差舍入(银行家舍入),不是四舍五入。附录提供了
round()自定义函数实现传统四舍五入。
|
|
速记重点小结
-v var=val:唯一可以在BEGIN块之前设置变量;直接命令行var=valBEGIN不可见。$0整条记录;$1~$NF字段;$NF最后字段。- 数组全部是关联数组;判断下标存在用
if(key in arr),不能直接if(arr[key])。 - NR全局记录号;FNR每个文件单独行号;RS记录分隔;FS字段分隔;OFS/ORS输出分隔。
next:读下一行回到脚本开头;exit退出但END仍然执行。sub()只替换第一个匹配;gsub()全局全部替换。system()只能拿到命令退出码,拿不到输出;拿输出必须用管道cmd | getline。sprintf()返回字符串,不输出;printf直接输出。**、delete arr清空整个数组属于扩展,非POSIX,跨平台脚本慎用。- printf
*可以动态设置宽度精度;C库默认银行家舍入,需要传统四舍五入自己写round函数。
文章作者 会写代码的小郎中
上次更新 2011-08-12
许可协议 CC BY-NC-ND 4.0