【转】 awk 学习笔记
本文参考的是 ubuntu 下 gawk version 3.1.6 以及 《sed&awk》
一 . awk 简介
awk 是一种解释型(tawk除外)文本处理语言
二 . awk 如何运作
命令行参数
shell 会预处理命令行,获得命令行参数(其中包括命令名),之后启动命令并向它传递剩余的参数。
系统变量ARGV:
一个关联数组,存放命令行参数,数组下标从0到ARGC-1,ARGV[0]的值为awk
系统变量ARGC:
命令行参数的个数
ARGV 的元素不包含AWK的选项和脚本
笔者根据 awk 的 info 手册以及实际操作,臆测出 awk 的大致运作过程如下:
1 . 执行 -v 选项指定的赋值语句
2 . 编译awk脚本为某种内部形式(internal form)
3 . 执行 BEGIN 块
4 . #如果没有提供输入文件
if(ARGC == 1)
{
#读取标准输入直到输入结束
while(未读到到文件末尾)#文件指标准输入
{
读取下一个记录
执行awk脚本
}
}
#遍历存放命令行参数的数组ARGV
for(i = 1; i < ARGC; i++) #ARGV[0]是awk,不作为输入文件
{
if(ARGV[i] 是var=val形式)
{
定义全局变量var的值为val
}
else #作为文件名处理
{
if(ARGV[i] 是有效的文件名)
{
while(未读到文件 ARGV[i] 的末尾)
{
读取下一个记录
执行 awk 脚本
}
}
else
{
输出错误,指出文件名ARGV[i]无效
}
}
}
5 . 执行 END 块
从以上的流程可以看出:
1 . BEGIN 块中 可以获得步骤 1 中赋值语句的变量值
2 . BEGIN 块中不可以获得步骤 4 中赋值语句的变量值
读者可以观察以下脚本的运行结果:
$ touch file1 file2 'c=30' #创建三个文件
$ cat file1
1111
2222
$ cat file2
3333
4444
$ cat file3
5555
6666
$ cat 'c=30' #文件名是赋值语句的形式
c=30
c=30
$ cat test1.awk
BEGIN{
print "---------------------"
print "当前在 BEGIN 块中"
print "a=" a
print "b=" b
print "c=" c
print "共有" , ARGC , "个命令行参数:"
for(i = 0; i < ARGC; i++)
print i , ARGV[i];
}
{
if(FNR == 1)
{
print "---------------------"
print "当前正处理文件" , FILENAME
print "a=" a
print "b=" b
print "c=" c
}
print "第" , FNR , "行", $0
}
END{
print "---------------------"
print "当前在 END 块中"
}
$ awk -v a=10 -f test1.awk file1 b=20 file2 c=30 file3
---------------------
当前在 BEGIN 块中 #注意到BEGIN只执行一次,而且是在输入之前
a=10 #BEGIN块里只认识通过 -v 选项赋值的变量a
b= # 不认识
c= # 不认识
共有 6 个命令行参数: #注意到,参数里面没有选项(-f)
0 awk #也没有作为脚本的文件名test1.awk
1 file1
2 b=20
3 file2
4 c=30
5 file3
---------------------
当前正处理文件 file1
a=10 #-v 选项赋值的变量,所有文件都认识
b= # 读入file1之后b=20才执行,file1不认识b
c= # c 是谁file1也不知道
第 1 行 1111
第 2 行 2222
---------------------
当前正处理文件 file2
a=10 #-v 选项赋值的变量,所有文件都认识
b=20 #b=20发生之后才读入file2,所以认识b
c= #肯定不认识
第 1 行 3333
第 2 行 4444
---------------------
当前正处理文件 file3
a=10
b=20
c=30 #原来,尽管当前目录下有名叫'c=30'的文件,但awk仍然把它当成赋值语句了
第 1 行 5555
第 2 行 6666
---------------------
当前在 END 块中 #注意到END发生在所有输入完毕之后
$
三 . 字符串常量
字符串常量是包括在两个双引号之间的一系列字符。
awk 能够像 C 语言一样识别字符串常量中如下转义字符:
// 字面反斜杠
/a 响铃(alert)
/b 退格键(backspace)
作用:删除光标左边的字符并使光标左移一格
/f 进纸键(form-feed)
作用:不清楚
/n 新行符(newline character)
/r 回车符(carriage return)
/t 水平制表符(horizontal tab)
/v 垂直制表符(vertical tab)
/xhexdigits 转义/x之后的 16 进制字符串为对应的字符
/x1B 代表 ESC 字符
/ddd 将 一位,两位,三位的十进制数转化为对应的字符
/033 或 /33 代表 ESC 字符
/c 字面的 字符 c
注意:
以上转义序列能够被 awk 的正则表达式识别!!
四 . 正则表达式
gawk 默认支持 POSIX ERE , GAWK 独有的转义序列, 以及 gawk 字符串常量支持的 C 类的转义序列。
POSIX ERE 支持以下形式的正则表达式:
c 匹配单个非元字符c
/c 匹配字面的元字符c
^ 匹配字符串开始
$ 匹配字符串结束
. 匹配任意字符,含换行符
[] 匹配方括号中出现的任意字符
[^] 匹配其中没有出现的字符
REGEXP1|REGEXP2 匹配REGEXP1 或者 REGEXP2
REGEXP1REGEXP2 匹配REGEXP1 紧接着匹配 REGEXP2
REGEXP+ 匹配REGEXP 的一次及以上出现
REGEXP? 匹配REGEXP 的 0 次或 1 次出现
REGEXP* 匹配REGEXP 的 0 次及以上出现
(REGEXP) 匹配REGEXP , 分组
REGEXP{n} 匹配REGEXP的 n 次出现
REGEXP{n,m} 匹配REGEXP的 n 到 m 次出现
REGEXP{n,} 匹配REGEXP的 最少 n 次出现
REGEXP{,m} 匹配REGEXP的 最多 m 次出现
字符类 [:alnum:]等
等价类 [=e=]等
collating class [.ch.] 等
GAWK 独有的转义序列
/y 匹配单词开头或者结尾的空串
/B 匹配单词内部的空串
/` 匹配缓冲区开头的空串
/' 匹配缓冲区结尾的空串
/w 匹配字母数字下划线(word-constituent character)
/W 匹配非字母数字下划线(no word-constituent character)
/< 匹配单词开头的空串
/> 匹配单词结尾的空串
awk 支持的 C 类转义序列也被 gawk 正则表达式支持:
/n
/r
/t
/v
/a
/b
/xhexdigits
/ddd
五 . 选项
-F fs
指定fs 为字段分隔符(field separator)
-f script
将script的内容添加到脚本中去。
-f可以出现多次,awk会按顺序把所有的脚本文件拼接作为一个完整的脚本
-v var=val
设置变量var 的值为 val,改变量赋值发生在BEGIN块之前
如果在赋值语句var=val中出现空格,可以使用引号将该语句包围,以此保护空格
以下选项关乎awk对正则式的理解:
--posix
支持POSIX ERE(包括范围表达式)
支持 awk 字符串常量支持的转义字符
不支持上述 GAWK 独有的转义序列
--traditional
只支持传统的UNIX awk 正则表达式,以下均不支持:
1) 范围表达式
2) 字符类等
3) gawk 独有的转义序列(更加不支持了!)
4) awk 字符串常量所支持的那些 C 类转义序列
--re-interval
强制支持范围表达式,即使已经指定了 --traditional 选项
如果上诉三种选项均未指定,则 awk 对正则式作如下理解:
支持 POSIX ERE (除了范围表达式)
支持 GAWK 支持的特殊转义序列(/y /w等)
支持 AWK 字符串常量支持的特殊转义字符(/ddd等)
五 . 记录和字段
1 . 记录(record)
1) 记录默认由新行符分隔,新行符是内置系统变量记录分隔符RS(record separator)的值。
2) RS 通常是一个字符,这个字符用于分隔记录。
3) RS 如果是多个字符,则被作为正则表达式,输入文本中匹配该正则式的部分用于隔开记录。但是在兼容模式下,只取第一个字符被作为分隔符。
4) <<sed & awk>> :RS 是 awk 仅仅注意其第一个字符的唯一一个变量。
3) RS 设置为空串(""),则记录被空行分隔,此时,无论FS(域分隔符)被设置成什么值,字段是由新行符隔开的。
4) FNR 记录当前记录在当前输入文件中的编号,即当前记录是当前文件的第 FNR 个记录。
5) NR 记录已经读入的记录的个数
2 . 字段(field)
1) 字段分隔符FS(field separator)用于把记录分隔成多个字段
2) FS通常是单个字符,则字段由该字符分隔。
3) FS是空格时比较特殊,记录中的字段之间由任意数量空格,任意数量制表符的任意排列分隔。
4) FS含多个字符时被作为正则表达式
5) NF 记录当前记录中的字段数
6) FIELDWIDTH 变量一旦被设置,则 FS 的值会被忽略,即在字段分隔不起作用。
7) awk读入记录的同时把字段的值赋给了内置变量,有以下方式可引用字段:
----使用常量引用例如 $10
----使用变量引用例如 $i , $NF
----使用算式返回值例如 $(2+1)
----使用函数返回值引用例如 $int(1+1)
其中,美元符叫做字段引用操作符
8) 引用负数位置的字段将导致错误
9) 引用 $NF 之后的字段将导致 awk 自动生成该字段及之前本没有的字段并各赋值为空串,NF被修改,$0 被调整。
六 . 关联数组
awk 中所有的数组都是关联数组,表达了一种从字符串到字符串的映射关系。
1 . 关联数组特点
1) 物理组织无序
2) 模拟多维数组
3) 原理是字符串映射
2 . 下标
关联数组的下标是括在一对方括号之间的表达式列表,如果有多个表达式,则表达式间用英文逗号分隔。
1) 一维数组
数组是从一个字符串到另一个字符串的映射,key_str --> val_str ,前者是键。
-- arr[ key_str ] 形式,awk 访问以变量 key_str 的值为键的数组元素
有个例外,当 key_str 是一个数字时,awk 会把它转换为字符串,此时arr[key_str]等价于arr["key_str"]
-- arr["key_str"] 形式,awk 访问以字符串 key_str 为键的数组元素
-- 访问某个不存在的数组元素时,awk会创建该数组元素,数组元素初始化为空串
例子:
$ awk 'BEGIN{a[1] = "1111"; print "a[/"1/"]=" , a["1"]; print "a[ 1 ]=" , a[1] }' file
a["1"]= 1111
a[ 1 ]= 1111
$ awk 'BEGIN{a["1"] = "111"; print length(a); print a[var] ; print length(a)}' file
1 # print length(a)输出 a 的长度,当时有一个元素 a["1"]
# a[var] 相当于 print a[""],而a[""]元素不存在,输出空串
2 # awk 自动创建了数组元素 a[""]并初始化为空串 , 所以数组大小变为 2
$
2) 多维数组
多维数组通过在方括号之间用逗号隔开各维的键进行访问,所有的键值都被作为字符串。
数字键会被转换为字符串,其中,实数转换为字符串可能会丢失信息,实数转换受 CONFMT 的影响。
多维数组与一维数组遵循同样的映射原理:
通过把方括号中各字符串用系统变量 SUBSEP 的值衔接起来得到 key_str ,然后映射到 val_str 。
例子:
i = "30"
j = 20
a["mm",i,j] = "zhong" 相当于 a["30" , "30" , 20] = "zhong"
相当于 a["mm" , "30" , "20"] = "zhong"
意为把数组元素 a["mm/03430nn"] 赋值为串 "zhong",其中/034 是SUBSEP 的默认值。
3 . 删除
通过 delete arr["index"] 删除单个元素;delete arr 删除整个数组。
4 . 遍历
---方法1
while(key in arr) #遍历 arr 的所有键值,如果是多维数组,用(key1,key2,key3)放在 key 的位置。
---方法2
如果能够在构建数组的时候,用连续的或者大小有规律的键值,则可以用for循环遍历例如:
for(i = 1; i <= NF; i++)
arr[i] = $i;
for(i = 1; i <= NF; i++)
print arr[i];
六 . 操作符(按优先级逐渐降低)
() 分组操作符
$ 字段引用操作符
++ -- 递增递减
^ 指数
+ - ! 一元加,一元减,逻辑取反
* / % 乘除取模
+ - 二元加,二元减
space 字符串连接符,很牛逼!
| |& 管道I/O,用于print , printf,getline
< > 关系运算符
<= >=
!= ==
~ !~ 匹配,不匹配,字符串匹配的,超牛逼!
in 判断关联数组中是否存在以某个键为下标的元素
&& 逻辑与
|| 逻辑或
?: C格式的条件语句,expr?expr1:expr2,如果expr为真,则该条件语句值为expr1的值;否则expr2。
= += -= 赋值,^=是将指数运算的结果赋给左参数
*= /= %= ^=
八 . 语句格式
awk 程序的框架是由一个或者多个如下的语句组组成:
condition{ statements }
其中可能出现两个特殊语句组
BEGIN{ statements } 和 END{ statements }
1 . BEGIN 语句组(如果有),作为第一个语句组,-v选项赋值语句之后,第一个记录读入之前执行。
2 . END 语句组(如果有),作为最后一个语句组。在所有输入结束之后执行。
3 . 每次读入一个记录,剩下的语句组都要判断条件是否满足,如果满足就执行。
4 . condition{statements}的condition如果缺失,则对所有记录都执行方括号中的语句。
5 . statements 如果缺失,则默认执行 print 函数,输出 $0
6 . 左花括号({) 必须和condition在同一行,condition 和 { 之间可以隔着空白符。
7 . statements中的每个statement 可以用分号隔开
condition 语句可以是以下形式:
BEGIN
-v选项赋值语句之后,第一个记录读入之前执行方括号中的语句。
END
在所有输入结束之后执行方括号中的语句。
/REGEXP/
当前记录能够匹配正则表达式REGEXP时,才执行方括号中的语句。
正则式的匹配能力须参考上面的部分。
表达式
《sed&awk》:表达式通过计算返回一个值,表达式由数字,字符串常量,变量,操作符,函数和正则表达式组成。
利用表达式的值作为判断根据,如果为0或者空则不执行
condition && condition 和 condition || condition
表示两个条件的逻辑与 和 逻辑或
condition ? condition1 : condition2
当condition满足时,如果condition1满足则执行方括号中的语句;
否则,当condition2满足时则执行方括号中的语句。
(condition)
就是把条件用括号包围起来而已
! condition
当condition不满足时,才执行方括号中的语句。
condition1 , condition2
从第一个满足condition1的记录开始(包含),到该记录之后第一个满足condition2的记录结束(含该记录)
都执行方括号中的语句。
例子:
# 不是BEGIN的条件下
! BEGIN{ statements }
# 注意左花括号之前可以有很多空白符
# 注意使用圆括号将表达式括起来不是必须的
0{ statements_impossible_to_execute }
1 - 1{ statements_impossible_to_execute }
(1+1) { statements_doomed_to_excute }
# 注意匹配的是扩展的正则表达式(ERE)
/^/t+/{ statements }
# 注意使用ERE的范围表达式时需要有 --posix 或者 --re-interval 选项
awk --posix '/a{2,4}/{print}' data
八 . 系统变量
FS 字段分隔符
RS 记录分隔符
OFS 输出字段分隔符,默认为空格;影响print的输出。
print $0 输出当前记录,字段之间由OFS的值隔开;
print "a" , "b" a和 b 之间由 OFS值隔开。
ORS 输出记录分隔符,默认为新行符;影响print的输出。
每个 print 语句最后都会输出 ORS 的值
ARGV 关联数组,用于存储传递给 awk 的输入文件名
有 ARGC 个元素,下标因此从0 到 AGRC-1
ARGV[0] 等于 "awk"
ARGV中的文件名如果是等式形式,则被awk作为赋值语句。
ARGC 数组ARGV中元素的个数,ARGC>= 1; 因为 ARGV[0] 是 "awk"
FNR 当前记录在当前输入文件中的位置,即当前文件的第FNR个记录
FILENAME 当前输入文件
RSTART 参考match 函数
RLENGTH 参考match 函数
SUBSEP 在多维数组的字符串映射中,用于把各维的键值衔接起来形成整体的键值
默认值是 "/034"
CONVFMT 数字转换的格式,默认值"%.6g"
ENVIRON 以环境变量名(大写)为键值的关联数组,可以通过环境变量名访问数组元素。
OFMT 数字的输出格式,默认是"%.6g"
还有一些系统变量,不熟悉,不写了:
ERRNO IGNORECASE LINT PROCINFO TEXTDOMAIN RT
九 . statements
statements 支持 C-style 条件和循环语句,break,continue ;以及其它语句。
------------------------------------------------------------------------------------
if(条件){语句组}[else {语句组}]
while(条件){语句组}
do{语句组}while(条件)
for(语句1;语句2;语句3){语句组}
for(var_key in arr){语句组}
break
continue
delete arr[i]
delete arr
exit [exitcode]
十 . 函数
1 . 算术函数
int ()
返回强制转换后得到的整数
cos(expr)
返回余弦值
sin(expr)
返回正弦值
atan2(y,x)
返回以弧度计算的(y/x)的反正切值
loh(expr)
返回自然对数值
exp(expr)
返回对数值
sqrt(expr)
返回开方后的值
rand()
返回随机产生的小于1大于等于0的值
srand([expr])
设置rand()函数的种子值为 expr 的返回值,如果没有expr 则以当天时间为种子。
<<sed&awk>>:如果没有调用srand(),awk在开始执行程序之前默认以某个常量为参数调用srand(),使得你的程序在每次运行时都从同一个种子数开始。
2 . 字符串函数
length()
返回字符串或者数组的长度
index(str,target)
返回字符串 target 在字符串 str 中第一次出现的位置,如果没有,返回 0;字符串下标从 1 开始。
match(str , /regexp/ , [, arr])
在字符串 str 中寻找匹配 regexp 的子串,返回第一个匹配子串的位置,如果失配,返回0。
设置系统变量 RSTART 为匹配子串的起始位置,RLENGTH为匹配子串的长度;失配则RSTART为 0 ,RLENGTH 为 -1。
如果 arr 这个数组,则 arr 被清空,并从下标 "1" 开始保存找到的匹配regexp的子串。
所有匹配的子串被保存在 arr["0"] 中。
split(str , arr [, /separator_regexp/])
把字符串 str 分解到数组 arr 中去,使用匹配正则式 separator_regexp 的子串作为分隔符。
如果没有提供 serarator_regexp 则使用 FS 的值作为分隔符。
返回分解得到的串的个数,即数组的大小(如果有)
sub(/regexp/ , replacement [,str])
把 str 中第一个匹配正则式 regexp 的子串替换成 replacement 字符串。返回替换的个数。
如果没有提供 str ,使用 $0 。
replacement 中出现的 & 具有特殊含义,被替换成匹配 regexp 的那部分子串。
要转义 replacement 中的 & 使用 //&
此外,& 必须被包含在双引号之间才能被识别,否则出错。
gsub(/regexp/ , replacement [,str])
把 str 中所有匹配正则式 regexp 的子串替换成 replacement 字符串。返回替换的个数。
其余说明与 sub 同。
tolower(str)
返回字符串 str 中所有大写字母全部被转换为小写字母之后的串。原串不改变。
toupper(str)
返回字符串 str 中所有小写字母全部被转换为大写字母之后的串。原串不改变。
substr(str , pos [,len])
返回 str 第 pos 个字符开始的长度为 len (len >=1) 的串
如果 len 未提供,则返回直到 str 末尾的串
如果 len <= 0 则返回空串
3 . 自定义函数
格式
function func_name(parameter_list){
statements;
return [rt_val]
}
1) 定义函数时,func_name 和左圆括号之间可以有空格,但是调用函数时不允许。系统自带函数例外。
2) 自定义函数中定义的变量具有全局性质,将它们定义在圆括号内的形式参数之后,可使成为局部变量。
3) 调用自定义函数时,实际参数不必包括函数内的局部变量。
4) 应该具有返回值,如果不显式返回,则默认返回空串。
5) <<sed&awk>>:自定义函数的定义可以放在脚本中模式操作规则可以出现的任何地方,通常可以放在脚本中模式操作规则之前。
4 . print
1) print
输出 $0 , 后跟 ORS
2) print expr_list
---每个表达式(expr)之间用逗号和空格的组合进行分隔。
---每个表达式的结果会被作为字符串输出,表达式之间输出OFS的值
---print 语句的最后输出 ORS 的值
---单个表达式内的串之间的空格符是作为字符串衔接符(print "x" "y" 相当于 print "xy")
---可以重定向到文件
---<<sed&awk>>: 规定 > 出现在任何打印语句的参数列表中时被看作是重定向操作符,如果想要 > 在参数列表中被看作关系运算符,可以使用圆括号将表达式或者参数列表括起来。
5 . printf("format_expression" [, arguments])
借用C程序设计语言printf进行格式化输出,括号可以省略。
format_expression 由双引号括起来,其中%之后的字符作为格式转换说明符; arguments 由逗号分隔,第 n 个
argument 对应于 format_expression 第 n 个 %转义说明符; 意为把该 argument
对应的串转换为该格式转换说明符指明的格式并输出。
以下为 % 与格式转换说明符的组合:
%c 作为ASCII字符输出
%d 作为整数输出
%i 作为整数输出
%e 以浮点格式输出
%E 以浮点格式输出
%f 以浮点格式输出
%g e或f的转换格式,长度最短,末尾的 0 被去掉
%G E或f的转换格式,长度最短,末尾的 0 被去掉
%O 作为无符号八进制数输出
%s 作为字符串输出
%u 作为无符号的十进制数输出
%x 作为无符号的十六进制数输出,a-f表示 10-15
%X 作为无符号的十六进制数输出,A-F表示 10-15
%% 字面的%
上述每一个格式转换说明符(除了%%之外)都可以扩充为以下形式:
%-width.precision format_specifier
width 指定域宽度,指定域宽的输出会自动向右对齐,如果想想左对齐,可以在百分号之后添加减号(-),见上式。
pricision 指定小数点之后的数字位数
数字的默认转换格式由系统变量 CONFMT (有的是OFMT) 指定,默认为 "%.6g"
也可以是以下形式:
% width.precision format_specifier
%0width.precision format_specifier
%+width.precision format_specifier
%#width.precision format_specifier
关于 printf 函数,不熟悉,只把参考文件贴出来:
- The expression should be left-justified within its field.
space For numeric conversions, prefix positive values with a space,
and negative values with a minus sign.
+ The plus sign, used before the width modifier (see below), says
to always supply a sign for numeric conversions, even if the
data to be formatted is positive. The + overrides the space
modifier.
# Use an “alternate form” for certain control letters. For %o,
supply a leading zero. For %x, and %X, supply a leading 0x or
0X for a nonzero result. For %e, %E, %f and %F, the result
always contains a decimal point. For %g, and %G, trailing zeros
are not removed from the result.
0 A leading 0 (zero) acts as a flag, that indicates output should
be padded with zeroes instead of spaces. This applies even to
non-numeric output formats. This flag only has an effect when
the field width is wider than the value to be printed.
width The field should be padded to this width. The field is normally
padded with spaces. If the 0 flag has been used, it is padded
with zeroes.
.prec A number that specifies the precision to use when printing. For
the %e, %E, %f and %F, formats, this specifies the number of
digits you want printed to the right of the decimal point. For
the %g, and %G formats, it specifies the maximum number of sig‐
nificant digits. For the %d, %o, %i, %u, %x, and %X formats, it
specifies the minimum number of digits to print. For %s, it
specifies the maximum number of characters from the string that
should be printed.
6 . getline
1) getline
读取下一个记录,覆盖$0,设置FNR NR NF
2) getline "-"
从标准输入读取一行
3) getline <"filename"
读入文件filename的下一个记录,只更新NF
4) getline var
读取下一个记录,存入变量var ,设置 FNR NR。 $0 不变,NF 不变
5) getline var <"file_name"
读入文件file的下一个记录,存入变量var 。 FNR NR NF $0均不变。
注:
1) 不能写成 getline() , 它的语法不允许有圆括号。
2) 返回值不是字符串
3) 成功读取返回 1 ;读到文件末尾返回 0 ;遇到错误返回 -1
4) 从流中/文件/管道中读取时,可以直接以字符串常量指定文件名,也可以通过变量提供。
7 . close
用于关闭已经打开的文件或管道,以此可以
1)限制打开的文件和管道的数量
2)关闭一个管道可以运行同一个命令两次
3)关闭一个管道使得其输出的成果可以被访问
例子2):
$ cat test.awk
{
"date" | getline var
print var
close("date") #关闭管道
"date" | getline var2
print var2
}
$ awk -f test.awk file
Fri Mar 4 21:35:09 CST 2011
Fri Mar 4 21:35:09 CST 2011
$ cat test.awk
{
"date" | getline var
print var
# close("date") #不关闭管道
"date" | getline var2
print var2
}
$ awk -f test.awk file #产生空行
Fri Mar 4 21:35:09 CST 2011
$
例子3):
$ cat test.awk
{
print $0 | "sort > outcome"
}
END{
close("sort > outcome") #关闭管道
while(getline var<"outcome"){
print var
}
}
$ cat data
aa
bb
ff
cc
$ awk -f test.awk data
$ cat outcome
aa
bb
cc
ff
$
8 . next
读入下一个记录,修改$0,NF ,NR , FNR
如果已经读到文件末尾,那么执行END块(如果有)
否则从第一个 condition{statements}重新开始执行
例子:
$ cat test.awk
{
print "next 前"
print "$0 =" $0
print "FNR=" FNR
print "NF =" NF
print "NR =" NR
next
print "next 后"
print "$0 =" $0
print "FNR=" FNR
print "NF =" NF
print "NR =" NR
}
END{
print "在 END 中"
}
$ cat data
aa bb
aa bb cc dd
$ awk -f test.awk data
next 前
$0 =aa bb #file的第一行
FNR=1
NF =2
NR =1
next 前 #注意,不是 "next 后"
$0 =aa bb cc dd #file的第二行
FNR=2
NF =4
NR =2
在 END 中
$
9 . nextfile
读入下一个文件的第一个记录,修改$0 , NF , NR , FNR
如果发现所有文件的输入数据都已经读完,执行END块(如果有)
否则从第一个 condition{statements}重新开始执行
10 . exit
exit 使得主输入循环退出并将控制转移到 END 规则,如果END存在的话。
11 . system("command_line")
执行 command_line , 返回命令的退出状态(exit status)
补充内容:
1 . 关于注释
与 sed 不同,awk 允许在程序的任何地方添加注释
2 . 关于断行的技巧
一种处理断行的方法就是使用 length 获得每个字段的长度,这样,当累计的长度超过某个特定的数据时,就可以指定一个换行。
3 . 看不懂的
注意, awk 和sed 不一样,不能“记住”前面的正则式,即不能用语法// 来引用最后的正则表达式。
第八章,有两个语句能影响输入循环,next 和 exit 。一些 awk 不允许在用户自定义的函数中使用 next 语句。exit
使得主输入循环退出并将控制转移到 END 规则,如果 END 存在的话。如果没有定义END 规则或者在end 中使用exit 则终止脚本的执行。
转自:http://blog.csdn.net/yaozhiyi/article/details/6224847
【转】 awk 学习笔记的更多相关文章
- linux awk学习笔记
awk学习笔记 awk语法格式 awk '{pattern + action}' {filenames} awk作用 awk的最基本功能是在文件或者字符串中基于指定规则浏览和抽取信息,awk抽取信息后 ...
- 【转】awk学习笔记
Awk学习笔记 整理:Jims of 肥肥世家 <jims.yang@gmail.com> Copyright © 2004 本文遵从GPL协议,欢迎转载.修改.散布. 第一次发布时间:2 ...
- awk 学习笔记
awk的语法有两种形式 awk [options] 'script' var=value file(s) awk [options] -f scriptfile var=value file(s) 选 ...
- sed and awk学习笔记
sed and awk 背景 awk起源追溯至sed和grep,进而追溯至共同的行编辑器ed.实用工具grep来源于ed命令:g/re/p .实用工具awk和sed有一个共同的选项-f用于指定脚本的名 ...
- awk学习笔记二:调用shell、文件执行(转)
awk 'BEGIN {print "Hello"}' 不操作文件直接处理数据流 要调用shell则可以用管道命令 如,打印日期awk 'BEGIN {"date&quo ...
- awk学习笔记一:基础(转)
awk内置变量 ARGC 命令行参数个数ARGV 命令行参数排列ENVIRON 支持队列中系统环境变量的使用FILENAME awk浏览的文件名FNR 浏览文件的记录数FS 设置输入域分隔符,等价于命 ...
- awk学习笔记
1. 数据格式 id1,n1 id2,n2 ... 要对每个id进行一个n的加和 cat file1 | awk -F"," '{if(n[$1]>0){n[$1]=n[$1 ...
- 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式
正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...
- 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧
目录 学习笔记:CentOS7学习之二十五:shell中色彩处理和awk使用技巧 25.1 Shell中的色彩处理 25.2 awk基本应用 25.2.1 概念 25.2.2实例演示 25.3 awk ...
随机推荐
- LeetCode第[4]题(Java):Median of Two Sorted Arrays 标签:Array
题目难度:hard There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median ...
- 基于 Webpack 引入 jquery 插件的笔记
如果都是基于 webpack(npm 上有包),那就非常顺利: import $ from 'jquery' import 'jquery-modal/jquery.modal.min.css' im ...
- rjs 合并压缩完 js 后 js 不压缩的问题
线下用 requirejs 开发完后,代码上线前要用 rjs 将多个有依赖关系的 js 文件压成一个,然后某天居然发现压成一个的 js 文件,没有压缩!!!几万行的 js!!! 很显然,是 uglif ...
- 微信【跳一跳】 opencv视觉识别 + 物理外挂
视频连接:http://v.youku.com/v_show/id_XMzMyNDQxNTA0OA==.html?spm=a2h3j.8428770.3416059.1 初入门C++ 与 opencv ...
- bzoj:1230: [Usaco2008 Nov]lites 开关灯
Description Farmer John尝试通过和奶牛们玩益智玩具来保持他的奶牛们思维敏捷. 其中一个大型玩具是牛栏中的灯. N (2 <= N <= 100,000) 头奶牛中的每 ...
- [bzoj1223] [HNOI2002]Kathy函数
首先由题解可得TAT,f(i)=i当且仅当i在二进制下为回文串. 那么问题就变成了1~n中有多少个二进制下的回文串. 把m转成2进制后就是正常的统计了= =. f[i]表示二进制下,有多少个i位的回文 ...
- Gym101473A Gym101473E Gym101473F-前缀和
代码: #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #i ...
- Codeforces Round #328 (Div. 2)_A. PawnChess
A. PawnChess time limit per test 1 second memory limit per test 256 megabytes input standard input o ...
- VS2012 TFS解决离职后代码遗留未迁入问题
第一步: 在命令行中输入 C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\IDE 第二步: 根据用户查找该用户下workspac ...
- JS 监听浏览器各个标签间的切换
以前看到过一些网页,在标签切换到其它地址时,网页上的标题上会发生变化,一直不知道这个是怎么做的,最近查了一些资料才发现有一个 visibilitychange 事件就可以搞定,这里将介绍一下页面可见性 ...