gawk on windows
gawk 在 windows 和 linux 上, 对命令行的细节处理存在差异。
#linux
gawk -F ':' '{printf("%s\n", $1)}' 1.txt
:windows
gawk -F ":" "{printf(\"%s\n\", $1)}" 1.txt
在 windows 上, 需要用双引号包裹命令部分, 内部双引号需要转义。
术语
记录(record)
awk 读入的数据, 每一行(\n
)为一条记录。NR 表示已经处理的记录数, FNR 表示当前文件中已经被处理的记录数。
段(field)
awk 把记录分成若干行, 默认使用 [[:blank:]]
作为分割符, 也可使用 -F
指定, 分割符可以是某个字符, 可以是正则( / / 不是必须的)。
gawk -F "[[:digit:]{2,}]"
awk 定义了一些变量可以获取段的值
- $0 所有段
- $1 第一个段 …
- $n 第 n 个段
NF 表示当前被处理的段。
模式(pattern)
用来决定动作是否可以被执行, 起过滤记录的作用。
动作(action)
由花括号包裹起来的代码块, 是脚本的主体, 用来处理记录。
规则(rules)
awk 脚本由一个个规则组成, 用来处理输入的记录, 每个规则由 模式 和 动作组成。
命令行参数
- f 指定 awk 脚本
- F 指定列分隔符
- v 设置变量
- D 开启调试
- i 导入库文件
- l 加载扩展
命令行中可以定义一些变量, 供脚本使用, 有两个方式
# -v
gawk -v n=10 -f test.awk 1.txt
# before filename
gawk -f test.awk n=10 1.txt n=20 1.txts
脚本结构
awk 脚本结构如下所示
pattern{action}.....parrern{action}
....
function func() {}
....
每个 pattern{action} 叫做规则(rules), action 是逻辑执行块。
有些 pattern 应用于文件每一行, 用来过滤感兴趣的 record, 也可以在 action 块使用 if 语句来过滤, 此时 pattern 可是用逻辑运算符来组合。有些 pattern 只在特定位置生效, 为系统内置。多个规则按照定义顺序来执行, 但是 BEGIN/END, BEGINFILE/ENDFILE 例外, 他们的执行时机已被系统固定下来了。最佳实践中, 最好按执行时机的先后顺序来书写规则。
pattern
- 正则(7.1.1) 应用每行
- 表达式(7.1.2) 应用每行
- range(7.1.3) 应用每行
- BEGIN,END(7.1.4) 脚本开始/结束生效
- BEGINFILE,ENDFILE(7.1.5) 文件开始/结束生效
- empty(7.1.6) 应用每行
正则pattern
/regxstr/ {}
str ~ /regxstr/{}
$1 ~ /regxstr/{}
need_check ~ /regxstr/ {need_check 是一个变量}
表达式pattern
一般是逻辑表达式, 可判端真假, 下面的例子也是合法的具有真值表达式
#非 0
if (3.1415927)
print " A strange truth value"
#非空
if (" Four Score And Seven Years Ago" )
print " A strange truth value"
#非0?????
if (j = 57)
print " A strange truth value"
字段($i)和 action中的变量都可以是逻辑表达式的组成部分, 不过二者还是有区别
- $i 可以把当前行的某个字段
- 变量 只能是由历史行计算的中间结果
#每行都生效
$1 > 10 {print $2}
# 有效
{
sum=$2+$3+$4
}
sum>111{
print $1
}
# 无效果,系统无法得知 sum 的值
sum>111 {
sum=$2+$3+$4
print $1
}
range
形如 bgpat, edpat
, 其中 bgpat 和 edpat 不能是 range pattern, 同时 range pattern 也不能和其他的 pattern 组合, 但是 bgpat 和 enpat 可以是组合的。
接受规则如下:
- 一旦某行满足 bgpat , 则开始接受行
- 直到某行满足 enpat, 则停止接受行
- 可以多次打开关闭,直至文件最后一行
BEGIN/END
脚本开始/结束时生效, 若接受多个文件, 也只生效一次, 一般用于脚本的准备和清理。begin 规则执行时, awk 还没读入任何输入。end 规则会在读入输入后执行。一个文件中可以有多个 begin 规则, 他们的执行顺序取决于定义顺序, end 也一样。
我们知道 begin 规则不能读取记录, 但这也不是绝对的, awk 允许我们使用 getline 来提前读取记录。
# 读取两行
BEGIN{
getline tmp;
print tmp;
getline tmp;
print tmp;
}
由于历史原因, awk end 规则中不能读取 NF 和 $0(段), 同样可以用 getline 来获取。
begin 规则中也无法使用 next 和 nextfile, 因为主循环(读记录-匹配-处理)还没开始。end 规则亦然, 因为主循环已经结束。
BEGINFILE/ENDFILE
beginfile/endfile 规则是 gawk 独有特性。beginfile 在 gawk 读入第一行时执行, 比一般规则先执行;endfile 在 gawk 读入文件最后一行后执行。一个文件中也可以有多个 beginfile 规则, 他们的执行顺序取决于定义顺序, endfile 也一样。 beginfile 在 begin 后执行, endfile 在 end 之前执行。输入多个文件时, 每个文件都会触发 beginfile / endfile 规则。
** BEGINFILE 持有预定义变量 **
- FILENAME 当前文件名
- FNR 设为 0
- $i (field) 被清空 (As with the BEGIN and END rules#148)
beginefile 规则存在主要的目的
- 测试文件是否可读
不可读时, 错误信息保存在 ERRNO , 否则为空。测试 ERRNO 一旦不为空, 则 nextfile 跳过该文件, 使得脚本更加鲁棒。
if (ERRNO) nextfile;
- 设置自定义的文件解析函数
空规则
每条记录都会执行。
action
由若干个 awk 语句组成, 每个语句以分号或者换行隔开。所有语句用花括号包裹起来。action 可以省略, 此时 pattern 不能省略
gawk -e "/[[:digit:]]/" 1.txt
gawk -e "$0 ~ /[[:digit:]]/ {print $0}" 1.txt
读文件
列的分割
- 使用 -F 参数指定分割符, 支持正则
- FS 分隔符分割, 支持正则
FS=/[^a-z]/
#一个字符一列
FS=""
#整行作为一列
FS="\n"
- FIELDWIDTHS 宽度分割, 实用于非结构化数据, 很难找到适合的分割符
#数据不足, 不发生错误,但是 NF 等于实际的列数
#取三列,没取到的字符被舍弃
FIELDWIDTHS = " 2 3 4"
# * 表示剩余部分
FIELDWIDTHS = "2 3 *"
# 第一列跳过 1 个字符,相当于从第二个字符开始取两个字符,设为第一列
FIELDWIDTHS="1:2 3 4"
- FPAT 内容分割, 正则匹配的文本作为列
行的分割
- RS
getline 自由控制读入
getline 读取一条记录, 返回
- 1 成功读取
- 0 到文件末尾
- -1 遇到错误(文件打不开), 错误信息放到 ERRNO
- -2 重试,
PROCINFO[" input" ," RETRY" ]
会被设置
awk 中, 所有规则(除去 begin/end, beginfile/endfile) 执行一遍后, NR (包括NF, FNR, RT)自动加 1, 此时 NR 相当于行指针, 换句话说 0。如果 NR 指向最后一行, 执行 getline 并不会更新 NR 的值。
前面的讨论针对当前文件, getline 同样支持读取其他文件, 此时系统会维护多个 NR。如果通过管道获取数据, getline 的执行不会更新 NR 等。
{
if ((getline var) < 0){
print "ERROR"
} else {
print var
print $0
}
}
#原始数据
1
2
3
4
5
#输出
2
1
4
3
5 #本来NR应该设置为 6 但只有 5 条数据,NR 不更新
5
几种用法
- getline 从当前文件读取, 读到的内容存放到 $0
- getline var 从当前文件读取, 读取的内容存放到 var
- getline var < “1.txt” 从 1.txt 读取, 读到的内容存放到 var
- command | getline var 从管道中读取
tmp = substr($0, 10)
while ((tmp | getline) > 0)
print
close(tmp)
#另外一个例子
sortcom = " sort -r names"
sortcom | getline foo
...
close(sortcom)
- getline 与 合作进程(coprocess)
awk 支持, 把数据交给其他程序处理, 然后通过 getline 读取处理结果
print " some query"|& " db_server"
" db_server"|& getline
读取超时
gawk 支持通过 tcp/ip 协议获取网络数据, 引入读取超时, 可以提高程序的健壮性。PROCINFO[" input_name" , " READ_TIMEOUT" ] = timeout in milliseconds
Service = " /inet/tcp/0/localhost/daytime"
PROCINFO[Service, " READ_TIMEOUT" ] = 100
if ((Service |& getline) > 0)
print $0
else if (ERRNO != " " )
print ERRNO
重试
PROCINFO[" input_name" , " RETRY" ] = 1
输出
awk 处理完毕后, 结果可以输出(print / printf)到标准输出也可以到文件。OFS 和 ORS 分别控制输出的行分割符和列分割符。awk 可以使用 OFMT 控制输出数字的精度(本质 sprintf())。
OFS
print xx, bb, ccc,dd 输出多列时使用 OFS 作为分割符, 默认为空格
ORS
print xx print yy
输出多行时, 使用 ORS 作为行分割符, 默认为 \n
OFMT
控制输出数字的精度(位数), 默认为 %.6f
, 即保留小数后 6 位。
格式化字符串
printf 支持格式化字符串, 可以实现更精细的输出控制
格式控制字符
不同类型的数据, 需要不同的输出格式和显示方式, 格式控制字符就是来达成此目的的设计
- %a 浮点数(格式
[-]0xh.hhhhp+-dd
) - %c char
- %d 十进制数字
- %e 科学计数法
- %f 浮点数格式输出
- %g 科学计数法或者浮点数
- %o 八进制
- %s 字符串
- %u 无符号数
- %x 十六进制
格式修饰符
可以控制输出宽度, 对齐方式, 小数位数, 整数位数等
- N$ 位置修饰符
printf " %s %s\n" , " don't" , " panic"
printf " %2$s %1$s\n" , " panic" , " don't"
-
- 左对齐, 默认右对齐
printf "%-10s", "foo"
-
- 显示数字的正负号
print "%+d", -19, 10
#
输出十六/八进制数字显示0x
0
, %e %f 输出点, %g 输出后面的 00
空格替换成 0, 对数字有效, 宽度大于数字宽度有效
printf "%010d\n", 10
- width 指定输出宽度
- .prec 指定小数位数
输出重定向
#重定向到文件
print items >> output-file #追加,文件不存在则创建
print items > output-file #先删除在写入
#管道
print items | command
#协程
print items |& command
print $1 > " names.unsorted"
command = " sort -r > names.sorted"
print $1 | command
#另外一个
print $0 | "coreutils sort -k2 -t:"
report = " mail bug-system"
print(" Awk script failed:" , $0) | report
print(" at record number" , FNR, " of" , FILENAME) | report
close(report)
特殊文件
- /dev/stdin
- /dev/stdout
- /dev/stderr
- /dev/fd/N 使用其他打开的文件 N 为 文件描述符编号
- /net-type/protocol/local-port/remote-host/remote-port 网络文件
关闭
sortcom = " sort -r names"
sortcom | getline foo
...
close(sortcom)
为何要关闭打开的文件或者管道
- 防止 awk 耗尽自身进程空间的文件描述符
- 关闭文件促使 管道 flush 数据
变量
awk 支持自定义变量, 和 c 分享相同标识符定义规则。
定义
a="";
a="hello";
print a
赋值
- 赋值符号赋值
variable=value
- 参数
-v
赋值
#awk 程序中可以直接使用未赋值和未定义的变量,通过 awk -v var="value" 来赋值,类似 c 中 #ifdef xxx, gcc 可以 通过参数给 xxx 赋值
- var=value file var=value file 方式
awk '{print n}' n=3 file1 n=2 file2
#输出 3 2
使用未定义的变量
awk 使用未定义的变量不会发生错误, 相反会自动创建该变量, 并且赋予初始值, 类型不同初始值也不同
- string 赋值空串
- number 赋值 0
作用域
在规则中定义的变量是全局的, 可以在所有的规则和自定义函数中使用
FNR <= 3{
if (FNR==1){
a=1
}else if (FNR==2) {
b=2
}else if (FNR==3) {
c=3
}
print a b c
}
#output
1
12
123
自定义函数中定义的变量是局部的, 对外不可见。
常量
数字
#浮点数
3.4
#科学计数法
3.4e-2
#八进制
04
#十六进制
0xa
字符串
#字符串
"exp"
#支持续行
"hello\
world"
正则
#常规
/^regxp$/
#表示匹配
str ~ /regxp/
单独出现 /regxp/ 等同于 match(str, /regxp)
#表示没有匹配
str !~ /regxp/
鉴于读取每行脚本中间部分都会执行, 变量应该在 begin 部分声明。对于 gawk 还支持加强的正则, 正则常量前冠以 @, 用以显示表明为正则常量。
数字、字符串转换
串联
ab 或者 a b 这种叫做串联, 字符串、数字、变量都可以相互串联, 表示拼接。
a=1;b=4;a b #14
a=1;b=s;a b #1s
a$1
转换原则
字符和数字相互可以转换。
a=1;b=4;(a b)+4 #18
a=1;b=4;(a+b)+4 #9
强制转换
- a "" 强制转换成字符串
- a+0 强制转换成数字
内置变量
太多了, 不一一列举, 详情参看 (Effective AWK Programming#159)
控制 awk 行为相关
-
输入
- FIELDWIDTH 指定 field 的宽度, 按段宽度分割记录时要用到。
- FPAT 指定正则, 按正则分割记录时要用到
- FS 指定分割符, 按分割符分割记录时要用到, 支持正则
- RS 输入记录(行)分割符, 默认是
\n
。若为空, 则用空行分割, 也可以是正则
-
输出
- OFMT 控制 print , sprintf 打印数字的精度, 默认为
%.6g
, 即小数点后6位。 - CONVFMT posix 系统引入, 作用同 OFMT
- OFS 输出段分割符, print 输出默认使用空格作为分割符, 可以使用 ofs 来修改
- ORS 输出行分隔符, 默认为换行符
- OFMT 控制 print , sprintf 打印数字的精度, 默认为
-
数学
- PREC 指定浮点数的精度
- ROUNDMODE 指定数字近似规则 (Effective AWK Programming#392)
-
数组
- SUBSEP 指定多维数组下标的分割符, awk 中多维数组本质为一维数组, 假设 subsep=@, 则
a[1,2]=10
转换a[1@2]=10
- SUBSEP 指定多维数组下标的分割符, awk 中多维数组本质为一维数组, 假设 subsep=@, 则
-
其他
- IGNORECASE 为真(非空或者非0,) 则字符比较和正则匹配都会是大小写无关。会改变众多函数行为, 也会影响 行 和 列的分割。
- TEXTDOMAIN 用于程序国际化 ,参看 (Effective AWK Programming#351)
传递信息给脚本
-
ARGC / ARGV : 同 c 的定义, 不过 option 不被计算在内。
gawk -F ":" -f showtable.awk -v a="b" n=10 1.txt m=20 2.txt
输出gawk;n=10;1.txt;m=20;2.txt;off5rrr1;end1;
-
ARGIND: 表示当前正在处理的文件在 ARGV 中的 index。处理中途发生错误可以告诉调用者哪些文件已经成功处理, 那个文件发生错误。如果在 程序中改变 ARGIND , 则程序立即转到下一个文件。
-
ENVIRON: 系统环境变量, 为一个关联数组, 环境变量名为数组下标, 值为环境变量的值
-
ERRNO: 储存错误信息。BEGINFILE 中, getline, close 函数调用后, getline 重定向后, 如果发生错误, 原因(string)会被填写在 ERRNO 中。其他情况 ERRNO 储存错误码, 就像 c 的 errno。如果非系统错误发生
PROCINFO["errno"]=0
, 否则PROCINFO["errno"]=errno
-
FILENAME: 表示当前正在处理的文件名
-
FNR: 处理中文件的当前行, 转到下一个文件 FNR 重置为 1
-
NF: 处理中字段的编号, 转到下一行NF 重置为 1
-
NR: 自开始执行,处理过的记录(行)数, 可以指定其值来直接跳到某行开始处理
-
PROCINFO 太杂了看Effective AWK Programming
-
RLENGTH 由 match() 函数设置, 返回匹配到的子串长度, 没有匹配到返回 -1
-
RSTART 由 match() 函数设置, 返回匹配到的子串起始 index, 没有匹配到返回 0
-
RT 代指分隔符,当RS是固定匹配此时RS=RT。如果RS是正则匹配,则RT是RS正则匹配的值
-
SYMTAB 为一个数组, 下标为 awk 程序中定义的变量和数组名称,
a=10
等同于SYMTAB["a"]=10
。awk 解析完脚本后, SYSTAB 就被初始化了。
数组
awk 支持数组, 数组下标可以是数字, 也可以是字符串。awk 支持多维数组, 本质是一维数组, a[1,3]=4
被处理成 a[1SUBSEP3]=4
, 其中 SUBSEP 为可修改的变量。
awk 数组相当灵活, 无需指定数组大小, 元素类型也无需相同, 因为 awk 数组本质为关联数组, 换句话说 key 和 value 作为一个关联组共同作为一个数组元素。
元素引用
awk 数组元素的引用同 c 语言一致, a[index]
。对不存在的数组元素的引用, awk 会创建该元素, 设定其值为"", 即空字符串,并返回空字符串。
删除元素
delete arr[a]
元素存在测试
若想测试某个元素是否存在, 可以使用 index in array
if (2 in arr) {
print "exists"
}
元素遍历
for
实用于 Index 为数字的数组
for(i=1;i<=length(arr);i++){
print arr[i]
}
for..in..
此种方式更为通用
for(index in arr) {
print arr[index]
}
多维数组
多维数组的本质是一维数组, 只要数组的元素是数组, 就可以模拟出多维数组。另外 awk 还支持伪多维数组。
伪多维数组
多维数组 arr[a,b]
, 是一个一维数组, a b 解析成一个唯一的 index, awk 负责该解析工作。arr[a,b]
等价于 arr[aSUBSEPb]
, SUBSEP 为一个常量, 作为分割符。
c 风格多维数组
形如arr[a][b]
, 本质是一位数组, length(arr) 等于 a, arr[i]
是一个数组。遍历
for (nn in arr){
for (mm in arr){
print arr[nn][mm]
}
}
数组排序
可是使用 asort
和 asorti
对数组排序。他们的函数原型
asort(src, [dest, how])
asorti(src,[dest, how])
#src 为待排序数组
#dest 为排序后结果,可选
#how 排序方式, 为函数名
asort 对数组元素排序, asorti 对数组下标排序。排序结果可以写回原数组, 也可以写到新数组。排序结果统一使用数字来索引, 也就是会丢失原来的索引。
PROCINFO["sorted_in"]="@ind_str_asc"
asort(arr)
for (nn in arr){
asort(arr[nn])
for (mm in arr){
print arr[nn][mm]
}
}
# 对索引升序排列, 且对两个索引均排序, 实现多列排序效果
asort(arr, dest, "@ind_str_asc")
for(nn in dest) {
print dest[nn]
}
指定排序方式
- 通过
PROCINFO["sorted_in"]
指定 - 通过 asort 和 asorti 参数 how 指定
排序函数
内置
awk 内置丰富的内置排序函数, 参看 (Effective AWK Programming#179)
自定义
形如 function aa(i1, v1, i2, v2)
, i1, i2 为索引, v1, v2 为数组元素。两个例子
#按索引升序
function ind_asc(i1, v1, i2, v2) {
if (i1 > i2){
return 1
} else if (i1==i2) {
return 0
} else if (i1 < i2) {
return -1
}
}
#按元素升序, 假设是一维数组
function val_asc(i1, v1, i2, v2) {
if (v1 > v2){
return 1
} else if (v1==v2) {
return 0
} else if (v1 < v2) {
return -1
}
}
awk 多列排序
构建一个多维数组, 把需要排序的列作为索引, 把行存为数组的值。就可以实现多列排序。
流程控制
if -else
if (cond) doing some thing; else doing another
if (cond) {
doing some sthing
} else {
doing another
}
for
for (init-cond; exit-cond; change-cond) {doing some thing }
for (init-cond; exit-cond; change-cond) doing some thing
for (i in array)
do something with array[i]
while
while (condition)
body
do-while
do
body
while (condition)
switch
swich 只能在 gawk 中使用, 语法和 c 一样。
break
continue
和 c 语言一致
next
停止处理当前记录, 转到下一个记录。next 不被允许使用, 在:
- end / endfile 所有的记录已经处理完毕。
- beginfile 还没有读入记录。
- begin / end posix 标准不能使用, 强行使用会报错
- 用户自定义函数
nextfile
停止处理当前文件, 转到下一个文件。切换到下一个文件会导致:
- FILENAME 指向下一个文件
- FNR 重新重置为 1
- 重新执行初 begin 以外的规则
- endfile 被执行
- ARGIND 加 1
如果在 beginfile 中使用 nextfile , 则不会触发 endfile。其他 awk 不支持在函数中使用 nextfile, 但 gawk 可以。
exit
exit exit_code
, 停止脚本, 并且返回退出码给调用者。所处位置不同行为也有差异:
- begin 中使用 exit, 记录不会被读入, 如果有 end, 则会被执行
- end 中使用 exit, 则立即停止, 没有其他规则的执行。
- 非 begin / end 规则中使用, 停止执行后续规则, 也不处理后续的记录, 如果有 end 则执行。gawk 不执行 endfile。
发生错误时, 调用 exit 并返回错误码, 供调用者分析, 为最佳实践。
正则
awk 的正则支持比较完整的正则特性, 但是不支持 环视
- 量词
- 字符组(class)
- 分支
- 捕获组(capture group)
- 元字符
另外还支持 Posix 标准的 “元字符”
[:alnum:]
数字和字母[:blank:]
空格和 tab[:cntrl:]
控制字符:digit:]
数字[:graph:]
可打印也可见,空格非可见[:lower:]
小写[:print:]
可打印,即非控制符[:punct:]
punctation(标点), 非字母、数字、空格字符、控制字符[:space:]
空格字符,包括空格,\t, \v, \n, \r(回车), \f[:upper:]
大写[:xdigit:]
16进制
使用时, posix 元字符和其他的没区别, 例如:[[:alnum:]]
匹配一个数字或字母
gawk 支持 gnu 标准的元字符
\s
空格\S
非空格\w
字(字母,数字,下划线)\W
非字
零长度断言, 用来断字
\<
开头空串(empty string)\>
结尾空串\y
开头或结尾空串B
是\y
反面` buffer 开头的空串 \'
buffer 结尾的空串
gawk 默认支持 gnu 和 posix 元字符, 可使用 gawk 命令行选项来做选择
- —posix
- —tranditional
大小写
- IGNORECASE=1 敏感
- IGNORECASE=0 不敏感
匹配
- (动态正则表达式Dynamic Regexps) 匹配
#匹配
str ~regx
#不匹配
str !~regx
#匹配
regx 等价于 $0 ~regx
- match()
函数
awk 脚本也支持库的引入(Effective AWK Programming#p237)
用户自定义函数
和 c 类似。这里着重介绍返回函数结果的两种方式
- return
- 参数列表返回(类似 c 的指针和引用)
{
arr[NR]=$0
}
END{
copy(arr, dest)
for(nn in dest)
print dest[nn]
}
function copy(arr) {
for (mm in arr) {
dest[mm] = arr[mm]
}
}
内建函数
生成布尔值
- mkbool(exp)
数学运算
- atan2(y,x) 反正切
- cos(x)
- sin(x)
- exp(x)
- int(x) 取整
- log(x)
- rand() 0~1随机
- sqrt(x)
- srand(x)
字符串处理
length 取长度
length(str)
如果 str 省略, 则默认取 $0 的长度, 还可取数字的长度, 先转字符串, 再取位数
asort/asorti 排序
asort(src, [dest, how]) asorti(src, [dest, how])
排序
其具体用法参看, 数组排序
gensub/gsub/sub 替换
gensub(regexp, replacement, how [, target])
替换
通用替换函数, 使用正则来匹配目标字符串, 比 sub(), gsub( )更为强大。gawk 支持捕获组, /(.+) (.+)/ 有两个捕获组, 可是使用 \\1 \\2
来引用捕获组的内容。
- regexp 正则
- replacement 替换文本
- how 为数字, 多个匹配时指定替换位置, 若为 g 或 G 则替换所有匹配
- target 可选, 指定匹配对象, 若省略则为 $0
a = " abc def"
b = gensub(/(.+) (.+)/, " \\2 \\1" , " g" , a)
print b
gsub(regexp, replacement [, target])
替换
gsub 默认替换所有匹配的位置。
sub(regexp, replacement [, target])
替换
只替换第一个
index 搜索第一次出现位置
index(in, find)
在 in 中搜索 find, 返回首次发现的位置索引
match 匹配
match(string, regexp [, array])
正则匹配, 返回第一次匹配位置的索引, 无匹配则返回 0。通过 match 也可以很方便获取匹配的字符串, 有两种方式
- RSTART/ RLENGTH
match 会设置系统预定义变量 RSTART 和 RLENGTH。成功匹配, RSTART 储存起始位置, RLENGTH 存储长度, 否则 RSTART 为 0, RLENGTH 为 -1
- array
match 第三个参数不为空, 这是一个传出参数, 第一个元素恒为匹配的字符串, 如果有捕获组, 则后续元素为捕获组的内容。
match(p, /\\([^\\]+)\.cmd$/, get_name_ret)
substr(p, RSTART+1, RLENGTH-4)
get_name_ret[1]
patsplit/split 分割字符串
patsplit(string, array [, fieldpat [, seps ] ])
用正则表达式fieldpat匹配字符串string,将所有匹配成功的部分保存到数组array中,数组索引从1开始存储。返回值是array的元素个数,即匹配成功了多少次
- array 分割的字符串储存于此
- fieldpat 正则或者字符串, 用来分割字符串, 类似 FPAT, 未指定则为 FPAT
- seps 存储分割符, 为一个数组, 未匹配的则为分割符, gawk 填写, 为输出参数
split(string, array [, fieldsep [, seps ] ])
将字符串分割后保存到数组array中,数组索引从1开始存储。并返回分割得到的元素个数
- fieldsep 分割符, 为字符串, 省略则为 FS
- seps 为数组, 储存每次分割的分隔符
sprintf 格式化字符串
sprintf(format, expression1, ...)
格式化字符串, 非打印, 返回格式化的字符串
strtonum 字符串转数字
strtonum(str)
字符串转数字。str
- 0 开头, 解析为 八进制
- 0x 开头, 解析为十六进制
substr 取子串
substr(string, start [, length ])
字符索引从 1 开始, 返回取得的子串长度。
tolower/toupper
tolower(string)/ toupper(string)
大小写转换
输入输出函数
close
close(filename [, how])
用来关闭文件, shell 命令, 管道。管道为半双工文件, 此时 how 可为 from 和 to, 指明管道通信方向。
fflush
fflush([filename])
刷新文件的存储 buffer, 对暂存输出的文件来说, 完成后刷新很有必要。
时间函数
mktime
mktime(datespec [, utc-flag ])
把时间日期格式化文本转成时间戳, 发生错误返回 -1
- dataspec
YYYY MM DD HH MM SS [DST]
strftime
strftime([format [, timestamp [, utc-flag] ] ])
把时间戳转成人可以阅读的格式字符串。如果没有参数, 则 PROCINFO[" strftime" ]
指定时间格式, 支持的格式
- %a weekday name 缩写
- %A weekday name
- %b month name 缩写
- %B month name
- %c 基于地域(本地)的时间显示格式
- %d 1~31 日期
- %D 等于 %m/%d/%y
- %e day of month, 但填充空格如果只有一个数字
- %F 等于 ‘%Y-%m-%d’
- %g 当前周数, 1~53
- %H 小时, 00~23
- %I 小时, 01~12
- %j day of year, 0~366
- %M 分钟, 00~59
- %n newline
- %p 12小时制的 am/pm
- %r The locale’s 12-hour clock time
- %R 等于 ‘%H:%M’
- %S 秒数, 00~59
- %t tab
- %T 等于 ‘%H:%M:%S’
- %u 星期, 1~7
- %w 星期, 0~6
- %k 24小时制, 填充空格
- %l 12小时制,填充空格
systime
系统时间, 返回时间戳
位操作函数
and(v1, v2 [, . . .])
compl(val)
lshift(val, count)
or(v1, v2 [, . . .])
rshift(val, count)
xor(v1, v2 [, . . .])
获取类型
isarray
isarray(x)
typeof
typeof(x)
返回变量 x 的类型, 为字符串
- ” array”
- “regexp”
- “number”
- ” number|bool”
- ” string”
- ” strnum”
- “unassigned”
- ” untyped”
库函数
合并array
function join(array, start, end, sep,
result, i)
{
if (sep == " " )
sep = "
"
else if (sep == SUBSEP) # magic value
sep = " "
result = array[start]
for (i = start + 1; i <= end; i++)
result = result sep array[i]
return result
}
库
引用库, 两种方式
- 命令行
-i
- @include
# test1.awk
BEGIN {
print " This is script test1."
}
#test2.awk
@include " test1"
BEGIN {
print " This is script test2."
}
@include 支持相对路径
扩展
扩展是使用 awk 提供的接口, 其他语言写就, 编译生成的文件。
加载扩展
- 命令行使用 -l
- @load
gawk 会从环境变量 AWKLIBPATH
指定的路径中寻找扩展。
@load xxxx
{
print $0
}