没有合适的资源?快使用搜索试试~ 我知道了~
首页Awk one-liners explained 中文版
Awk one-liners explained 中文版

awk,文本处理,正则表达式。Awk one-liners explained 中文版
资源详情
资源评论
资源推荐

Awk one-liners explained 中文版
http://bbs.chinaunix.net/thread-1640657-1-1.html
首先声明,这篇文章并不是原创,这是我在学习 awk 的过程中,经 CU 的朋
友推荐,看到了 Peteris Krumin 关于 awk 的非常精彩的讲解,由于原文是英文版
的,英语水平稍差的朋友可能学习起来会有点困难,为了能够给正在学习 awk
的朋友们提供一点点帮助,也锻炼一下自己的英语水平,我将这些 awk 讲解翻
译了一下,加上了一点个人的看法,由于本人水平有限,错误肯定不少,欢迎高
手们批评指正,共同进步。谢谢。
http://www.catonmat.net/blog/awk-one-liners-explained-part-one/ 这是原文的链
接。。
废话不说,开始进入 awk 第一个部分:行距,编号和运算。
第一部分:行距,编号和运算
1、输出两倍行距文件
#more file
12 32423 -2354235
234532 23456 555555
-432346 45435 4462
#awk '1; { print "" }' file
12 32423 -2354235
234532 23456 555555
-432346 45435 4462
这个是如何运行的呢?每一个 awk 程序都是由一系列的 “模式—动作”语句组
成,即“模式{动作}”,在这个例子中有两个这样的语句,即"1" 和 "{ print "" }",
每个语句中无论是模式还是动作都可能不存在。如果模式部分不存在,默认匹配
所有行,那么就对每一行都执行动作。如果动作不存在,默认执行动作{print},
因此这个例子也可以写成这样:
#awk '1 { print } { print "" }' file
只有当模式正确匹配,动作才会执行,由于“1”始终是正确的,所以这个例子
可以写成两条打印的语句
#awk '{ print } { print "" }' file
在 awk 中每一条打印命令中后面都跟了一个输出记录分隔符(ORS),默认是换

行。第一个打印命令后面没有加参数,等同于{print $0},$0 是相应的每一条记录,
是可变的,通过设置输出记录分隔符(ORS)可以得到不同类型的记录。第二个
打印命令后面接的是“”(空),我们知道每个打印命令后面都跟了一个输出记录
分隔符,实际上打印了一个新行,因此打印出来以后每行之间有双倍的行距。
PS:例子中的分号的作用是将两条语句区分开来,如果不用分号 awk 会认为是
一个语句。其他两种写法不加分号是因为检测到有动作{print}存在,后面的内容
会自动认为是另一个语句。所以在 awk 中,当前一个语句只有模式而没有动作
时,后面要在加语句的话,必须要用分号区分开来,有动作时分号可有可无。
2、另一种方法输出两倍行距文件
#awk 'BEGIN { ORS="\n\n" }; 1' file
12 32423 -2354235
234532 23456 555555
-432346 45435 4462
BEGIN 是一种特殊的语句,这种语句不检测输入文件。也就是在读输入文件之前
运行。通过设置输出记录分隔符(ORS)为两次换行的方法实现输出两倍行距文
件。根据之前提到过的,语句“1”等同于{print},打印出来的每条记录之间的分
隔符都为前面设置的 ORS。
PS:一个完整的 awk 语句应该是这种形式
awk ‘BEGIN{动作};模式{动作};模式{动作}。。。 ;END{动作}’ file
其中 BEGIN{动作}和 END{动作}分别是在读输入文件之前和读输入文件之后执行,
通常用来制表和统计数据,很多时候都不必用到。只有中间的语句模式{动作}才
会读输入文件并对其执行动作。
3、输出两倍行距文件,并且任意两行之间只有一个空行存在。
首先修改一下 file,在里面加一个空行
#more file
12 32423 -2354235
234532 23456 555555
-432346 45435 4462
#awk 'NF { print $0 "\n" }' file
12 32423 -2354235
234532 23456 555555

-432346 45435 4462
这个命令使用了另一个 AWK 变量 NF(域的个数),意思是当前行被分割的数量,
比如 234532 23456 555555
这一行被分割成 3 个部分,因此得 NF 的值就是 3,空行的无法被分割,因此 NF
的大小就是 0.在模式中使用 NF 可以有效的过滤空行。这个命令的意思是:只要
行中存在域,就在此行的后面打印一个空行。
PS:当模式为数值(-1,0,1,1.1)时,只要数值不为 0,即为匹配所有行。
4、 三倍行距
#awk '1; { print "\n" }' file
12 32423 -2354235
234532 23456 555555
-432346 45435 4462
这个命令跟之前的很是相似,语句“1”等同于{print},因此也可以写成
#awk '{ print; print "\n" }' file
先打印一行,然后是打印输出记录分隔符(ORS),默认是换行。
PS:有些初学者在这里可能会有点疑惑(我刚开始也想了很久 O(∩_∩)O),不
过仔细想想就容易理解了。之前我们提到过,每个打印命令后面都跟了一个输出
记录分隔符(默认是换行),因此在这个命令中,先执行第一个语句:首先打印
文件的第一行,然后跟一个 ORS,也就是换行了,接着执行第二个语句{print “\n”},
\n 就是换行,这时候后面又跟一个 ORS,还是换行,因此出现了在每行之间出现
了 2 个空行。
5、给每个文件的行单独编号
#awk '{ print FNR "\t" $0 }' file
1 12 32423 -2354235
2 234532 23456 555555
3 -432346 45435 4462
这个 awk 程序在每行之前附加了一个文件行号(FNR)file line number 和一个 tab
(\t),FNR 包含了每一个文件当前行的行号。比如说,awk 针对两个文件做操作:

#awk '{ print FNR "\t" $0 }' file file
1 12 32423 -2354235
2 234532 23456 555555
3 -432346 45435 4462
1 12 32423 -2354235
2 234532 23456 555555
3 -432346 45435 4462
可以看到,结果是分别给两个文件的每一行之前加上该行在文件中的行号。FNR
给文件的行编号时,如果有多个文件会重新开始编号。
6、给所有文件的行一起编号
#awk '{ print NR "\t" $0 }' file file
1 12 32423 -2354235
2 234532 23456 555555
3 -432346 45435 4462
4 12 32423 -2354235
5 234532 23456 555555
6 -432346 45435 4462
这个命令和第五个例子几乎一样,唯一不同的地方是使用了参数(行号)NR-Line
Number。NR 与 FNR 不同的地方就在于 NR 在给多个文件的行编号的时候不会根
据文件重新编号,而是按照读取顺序统一编号。
7、花式编号
#awk '{ printf("%5d : %s\n", NR, $0) }' file
1 : 12 32423 -2354235
2 : 234532 23456 555555
3 : -432346 45435 4462
这个命令用了通常格式 printf()函数来给给行编号,像普通的 printf()函数一
样格式化参数。这里需要特别注意的是在 printf()函数后面不会附加一个输出
记录分隔符(ORS)。因此我们需要在每一行的后面明确的打印出一个换行符(\n)。
这个命令的结果是在每行之前打印行号和一个冒号。
8、只给非空行编号
#more file
12 32423 -2354235
234532 23456 555555
432346 45435 4462

#awk 'NF { $0=++a " :" $0 }; { print }'
1 :12 32423 -2354235
2 :234532 23456 555555
3 :-432346 45435 4462
Awk 参数都是动态的,在第一次使用的时候建立。这个命令指定 a 这个变量随着
行数的增加和不断自增长,空行除外(NF=0)。然后将这个参数的值和冒号附加
在每一行的开头并打印出来。
PS:在这个例子中,第一个语句是 NF{$0=++a”:”$0},模式是 NF,动作是一个
赋值语句$0=++a”:”$0,即当 NF 不为 0 的时候,在每一行的开头都加上一个变
量 a 和一个冒号,然后通过第二个语句打印出来。记住,在这里“=”不是等于
的意思,而是给$0 重新赋值,“==”才是等于的意思。
9、计算文件行数(与 wc –l 的作用类似)
#awk 'END { print NR }' file
4
前面提到过,END{}是一种不测试文件的特殊语句,它是在所有行遍历完以后执
行。在所有行遍历完以后,NR 就等于最后一行的行号,再出变量 NR 的值,就
是输出文件的行数了。
10、打印每行中域值的总和
#awk '{ s = 0; for (i = 1; i <= NF; i++) s = s+$i; print s }' file
-2321800
813543
-382449
awk 有很多地方借鉴了 c 的风格,比如这个 for(;;){„}循环。这个命令使用 for
循环遍历了每一行中的每个域(NF 即为每行中域的个数)。然后将每个域的值累
加给变量 s,最后打印出 s 的值,即为所有域相加后的值。
PS:如果把 s=s+$i 写成 s=s+i,则结果大相径庭
#awk '{ s = 0; for (i = 1; i <= NF; i++) s = s+i; print s }' file
6
6
6
因为前面的 s=$1+$2+$3,而后面的 s=1+2+3。
11、打印所有行中域值的总和
#awk '{ for (i = 1; i <= NF; i++) s = s+$i }; END { print s+0 }' file
-1890706
剩余24页未读,继续阅读

















安全验证
文档复制为VIP权益,开通VIP直接复制

评论2