分类: LINUX
2016-04-29 17:29:47
原文地址:[SHELL]awk的用法举例 作者:夏寥寥
从初学awk到现在小有所成,非常感谢CUers的帮助,总结了下自己曾经遇到的问题和犯的错误,供初学者借鉴,因本人非计算机专业,对专业词汇可能有表述不对的地方,还请指正和补充!
1. awk ‘{code}1’ 中的“1”是干什么的?
一个完整的awk语句为:Awk ‘[patten]{action}……’, 其中pattern缺省为1,action缺省为{print}。
那么awk ‘1’完整的写法就是awk ‘1{print}’; 同理,awk ‘{print}’完整的写法也是awk ‘1{print}’。
2. NR和FNR的区别是啥?
NR: 当前行记录数。
FNR: 当前文件的行记录数。
当awk处理的文件数超过1时,NR和FNR才会有区别。例如:
点击(此处)折叠或打开
3. Awk怎么引入变量?
有两种方法:
(1): awk -v var=$VAR '{code}'
(2): awk '{CODE}'$VAR'{CODE}'
例如:
点击(此处)折叠或打开
4. 为什么OFS不起作用?
先看一个例子:
点击(此处)折叠或打开
点击(此处)折叠或打开
正如Tim大师所讲的,$1=$1这个action,是我们对awk撒的谎,目的就是为了使得OFS生效,除此之外,NF+=0也是常用的方法。参考:
5. 同样的代码,别人运行成功,为什么我运行失败?
这个问题的原因很多,我这里列举两个最常见的,大家可以补充。
<1>: awk版本引起的,如gawk中的一些扩展函数或变量,在nawk中没有,或是不同版本的(g/n)awk也会有差别,这样情况需要重新编写。
<2>: 文本格式的问题,cat-A file查看一下,如果是,dos2unix应该可以解决。
注:书写错误也有可能哦.
6. Awk 语句中可以使用{n,m}这样的正则么?
可以,使用方法:gawk -- re-interval ,其它版本使用方法会有所不同,请大家补充
7. BEGIN 和END 到底是怎么一回事?
有时,对于新手可能也会是个问题。简单说下:
BEGIN {action} : 读取文本之前进行的操作。要避免类似下面的写法:
点击(此处)折叠或打开
如果BEGIN 模块中使用getline函数时,情况会有所不同:
点击(此处)折叠或打开
END {action}:
它在整个输入文件处理完成后被执行,同样无法对文本进行任何操作,如匹配某个pattern执行action。
8. print,printf 和sprintf?
print:为一般的打印
printf:可以定义打印格式
sprintf:可以完成和printf相同的功能,不同的是sprintf只能输出值,并不能完成打印的功能。
print默认有个换行\n,而printf没有,当然它和C语言的printf类似(awk本是c的近亲),能打印各种格式,但默认没有换行。
例如:
点击(此处)折叠或打开
9. “a==b?c:d” ?
这个是一个if语句的简写,即conditional expression1 ? expression2: expression3;完整写法为:
if(a==b) {c} else {d}
10. awk ‘! a[$0]++’ 怎么理解?
这是一个非常经典的去重复项的awk语句,虽然短小,不过涉及到了不少知识点,下面一一解读:
<1> :”!” 即非。
<2>:a[$0],以$0为数据下标,建立数组a
<3>:a[$0]++,即给数组a赋值,a[$0]+=1
<4> :那么组合起来,awk是怎么执行!a[$0]++的呢?我用一个实际例子来解释:
点击(此处)折叠或打开
原来,第一个a[$0]的值为空,所以!a[$0]++是先作判断,结果为1(非空为真,即为1),再作数组赋值a[$0]++。这也就是为什么前面的!a[$0]++并不一定等于后面的!a[$0]。
awk ‘++a[$0]==1’ 和上面的代码作用一样,你理解了么?
11. 如何打印单双引号?
点击(此处)折叠或打开
点击(此处)折叠或打开
12. awk 语句中多个{}是怎么执行的?
还是用个例子来说明:
点击(此处)折叠或打开
这样可以清楚的看出,awk是一行一行读取文本,然后按照代码的前后顺序执行。但如果action中包含next或exit时,有所不同:
点击(此处)折叠或打开
13. FS, OFS, RS, ORS?
最后用图解的方式说明一下这四个变量:
gsub(r,s) |
在整个$0中用s代替r |
gsub(r,s,t) |
在整个t中用s替代r |
index(s,t) |
返回s中字符串t的第一位置 |
length(s) |
返回s长度 |
match(s,r) |
测试s是否包含匹配r的字符串 |
split(s,a,fs) |
在fs上将s分成序列a |
sprint(fmt,exp) |
返回经fmt格式化后的exp |
sub(r,s) |
用$0中最左边最长的子串代替s |
substr(s,p) |
返回字符串s中从p开始的后缀部分 |
substr(s,p,n) |
返回字符串s中从p开始长度为n的后缀部分 |
gsub函数有点类似于sed查找和替换。它允许替换一个字符串或字符为另一个字符串或字符,并以的形式执行。第一个函数作用于记录$0,第二个gsub函数允许指定目标,然而,如果未指定目标,缺省为$0。
index(s,t)函数返回目标字符串s中查询字符串t的首位置。length函数返回串s字符长度。
match函数测试字符串s是否包含一个正则表达式r定义的匹配。
split使用域fs将字符串s划分为指定序列a。
sprint函数类似于printf函数,返回基本输出格式fmt的结果字符串exp。
sub(r,s)函数将用s替代$0中最左边最长的子串,该子串被r匹配。
substr(s,p)返回字符串s在位置p后的后缀。
substr(s,p,n)同上,并指定子串长度为n。
此外,$0变量是指整条记录。$1表示当前行的第一个域,$2表示当前行的第二个域,......以此类推。
awk中的gsub的&,表示要被替换的原始字符。gsub(/[0-9]+/,”\\0x&”),这时&表示[0-9]所匹配到的字符。
15.awk常见错误检查
当第一次使用awk时,可能被错误信息搅得不知所措,但通过长时间和不断的学习,可总
结出以下规则。在碰到 awk错误时,可相应查找:
? 确保整个awk命令用单引号括起来。
? 确保命令内所有引号成对出现。
? 确保用花括号括起动作语句,用圆括号括起条件语句。
? 可能忘记使用花括号,也许你认为没有必要,但 awk不这样认为,将按之解释语法。
?正则表达式用斜线括起来! \ ^ $ . [] | () * + ?
ARGC:支持命令行中传入 a w k脚本的参数个数。
ARGV:是ARGC的参数排列数组,其中每一元素表示为ARGV[n], n为期望访问的命令行参数。
ENVIRON :支持系统设置的环境变量,要访问单独变量,使用实际变量名,例如
ENVIRON [“ EDITOR”] =“Vi”。
FILENAME:支持awk脚本实际操作的输入文件。
因为awk可以同时处理许多文件,因此如果访问了这个变量,将告之系统目前正在浏览的实际文件。
FNR:支持awk目前操作的记录数。其变量值小于等于 NR。如果脚本正在访问许多文件,
每一新输入文件都将重新设置此变量。
FS:用来在awk中设置域分隔符,与命令行中 - F选项功能相同。缺省情况下为空格。
如果用逗号来作域分隔符,设置 FS = ","。
NF:支持记录域个数,在记录被读之后再设置。
OFS:允许指定输出域分隔符,缺省为空格。如果想设置为 #,写入OFS = "#"。
ORS:为输出记录分隔符,缺省为新行(\n)。
RS:是记录分隔符,缺省为新行 (\n)。
域值比较操作
有两种方式测试一数值域是否小于另一数值域。
1) 在BEGIN中给变量名赋值。
2) 在关系操作中使用实际数值。
通常在BEGIN部分赋值是很有益的,可以在awk表达式进行改动时减少很多麻烦。
使用关系操作必须用圆括号括起来。
AWK内置字符串函数
从shell中向awk传入字符串
(1) 使用管道将字符串stand-by传入awk,返回其长度。
(2) 设置文件名为一变量,管道输出到awk,返回不带扩展名的文件名。
(3) 设置文件名为一变量,管道输出到awk,只返回其扩展名。
字符串屏蔽序列
printf修饰符
向一行awk命令传值
在查看awk脚本前,先来查看怎样在 awk命令行中传递变量。
在awk执行前将值传入awk变量,需要将变量放在命令行中,格式如下:
awk 命令变量=输入文件值
在awk中使用F S变量
使用awk脚本时,记住设置 FS变量是在 BEGIN部分。
向awk脚本传值
格式:awk script_file var=value input_file
awk数组
数组使用前,不必定义,也不必指定数组元素个数。经常使用循环来访问数组。下面是
一种循环类型的基本结构:for (element in array ) print array[element]