Chinaunix首页 | 论坛 | 博客
  • 博客访问: 184022
  • 博文数量: 28
  • 博客积分: 648
  • 博客等级: 上士
  • 技术积分: 260
  • 用 户 组: 普通用户
  • 注册时间: 2010-12-17 05:33
文章分类

全部博文(28)

文章存档

2012年(1)

2011年(27)

分类: LINUX

2011-04-26 08:13:05

从初学awk到现在小有所成,非常感谢CUers的帮助,总结了下自己曾经遇到的问题和犯的错误,供初学者借鉴,因本人非计算机专业,对专业词汇可能有表述不对的地方,还请指正和补充!


1. awk ‘{code}1’ 中的“1”是干什么的?

一个完整的awk语句为:Awk ‘[patten]{action}……’, 其中pattern缺省为1,action缺省为{print}。

那么awk ‘1’完整的写法就是awk ‘{code}1{print}’; 同理,awk ‘{print}’完整的写法为awk ‘1{print}’。


2. NR和FNR的区别是啥?

NR: 当前行记录数。

FNR: 当前文件的行记录数。

当awk处理的文件数超过1时,NR和FNR才会有区别。例如:

cat file

a
b
c
d
e
f

awk '{print "NR = " NR "  FNR = " FNR, $0}' file

NR = 1  FNR = 1 a
NR = 2  FNR = 2 b
NR = 3  FNR = 3 c
NR = 4  FNR = 4 d
NR = 5  FNR = 5 e
NR = 6  FNR = 6 f

awk '{print "NR = " NR "  FNR = " FNR, $0}' file file

NR = 1  FNR = 1 a
NR = 2  FNR = 2 b
NR = 3  FNR = 3 c
NR = 4  FNR = 4 d
NR = 5  FNR = 5 e
NR = 6  FNR = 6 f
NR = 7  FNR = 1 a
NR = 8  FNR = 2 b
NR = 9  FNR = 3 c
NR = 10  FNR = 4 d
NR = 11  FNR = 5 e
NR = 12  FNR = 6 f


3. Awk怎么引入变量?

有两种方法:

<1>: awk -v var=$VAR '{code}'
<2>: awk '{CODE}'$VAR'{CODE}'
例如:

VAR=XXX

awk -v var=$VAR 'BEGIN{print var}'

XXX

awk 'BEGIN{print "'$VAR'"}'

XXX

我推荐使用第一种方法,这样可以避免一些不必要的烦恼。如


4. 为什么OFS不起作用?

先看一个例子:

echo 'aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd' |awk -v OFS="|" '{print $0}'

aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd

上面的例子中OFS为什么没有生效呢,原因是OFS指的是输出字段分隔符,所以必须对字段进行操作时OFS才会起作用,正确的方法应该是:

echo 'aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd

aaa bbb ccc ddd' |awk -v OFS="|" '{$1=$1;print $0}'
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd
aaa|bbb|ccc|ddd

正如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}这样的正则么?

可以,不过是一种GNU的扩展,使用方法:gawk -- re-interval


7. BEGIN 和END 到底是怎么一回事?

有时,对于新手可能也会是个问题。简单说下:

BEGIN {action} : 读取文本之前进行的操作,所以不可以妄想在BEGIN的{action}中,对文本进行任何操作,或获取任何文本的信息。要避免类似下面的写法:

awk 'BEGIN{ filename =  FILENAME}' file

# or:

awk 'BEGIN{FS=":"; for(i=2;i<=NF;i++) print $i}' file

END {action}:
它在整个输入文件处理完成后被执行,同样无法对文本进行任何操作,如匹配某个pattern执行action。


8. print,printf 和sprintf?

Print:为一般的打印

print:可以定义打印格式

sprintf:可以完成和printf相同的功能,不同的是sprintf只能输出值,并不能完成打印的功能。

例如:

awk 'BEGIN{var=123; print "var = " var}'

var = 123


awk 'BEGIN{var=123;printf "%s %5f\n", "var =",var}'

var = 123.000000


awk 'BEGIN{var=123;sprintf ("%s  %5f\n", "var =",var)}'



awk ‘BEGIN{var1=123;var2=sprintf ("%5f",var1); print "var2 =" var2}’

var2 = 123.000000


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]++的呢?我用一个实际例子来解释:

cat file
111
222
111
222
333

awk '{print a[$0],!a[$0]++,a[$0],![$0],$0}' file
  1 1 0 111
  1 1 0 222
1 0 2 0 111
1 0 2 0 222
  1 1 0 333

原来,第一个a[$0]的值为空,由于“!”的运算级别高于“+”,所以!a[$0]++是先作判断,结果为1(非空为真,即为1),再作数组赋值a[$0]++。这也就是为什么前面的!a[$0]++并不一定等于后面的!a[$0]。

awk ‘++a[$0]==1’ 和上面的代码作用一样,你理解了么?


11. 如何打印单双引号?

awk 'BEGIN {print "single quote --> '\''";print "double quote --> \"" }'

single quote --> '

double quote --> "


12. awk 语句中多个{}是怎么执行的?

还是用个例子来说明:

cat file

1

2

3

4

5


awk '$1==3{printf "|| "$0}{printf " @@ "$0}{print $0}' file # 这个语句中包含三个action

@@ 11   # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

@@ 22   # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

|| 3 @@ 33  # 判断$1==3?是,执行{print “|| “$0}; 执行 action {printf " @@ "$0};执行 action {print $0}

@@ 44  # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

@@ 55  # 判断$1==3?否;执行 action {printf " @@ "$0};执行 action {print $0}

这样可以清楚的看出,awk是一行一行读取的,按照代码的前后顺序,从头到尾执行。但如果action中包含next或exit时,有所不同:

awk '$1==3{printf "|| "$0;next}{printf "@@ "$0}{print $0}' file

@@ 11

@@ 22

|| 3@@ 44

@@ 55


awk '$1==3{printf "|| "$0;exit}{printf "@@ "$0}{print $0}' file

@@ 11

@@ 22

|| 3


13. FS, OFS, RS, ORS?

最后用图解的方式说明一下这四个变量:

(38.66 KB)

Picture2.png

阅读(2207) | 评论(3) | 转发(0) |
0

上一篇:解读:bash去重复

下一篇:read -u

给主人留下些什么吧!~~

longber2011-07-26 23:20:28

杯具的是公司新的系统是用.Net开发的,实在没兴趣去学powershell了..

longber2011-07-26 23:19:37

恩,学习!

2011-05-08 11:55:49