awk中 FS、NF、NR、RT、RS、ORS、OFS用法
AWK工作流程:逐行扫描文件,从第一行到最后一行,寻找匹配特定模式的行,并在这些行上进行用户想要到的操作。
AWK基本结构有模式匹配和处理过程(即处理动作)组成。
pattern {action}
awk读取文件内容的每一行时,将对比该行是否与给定的模式相匹配,匹配则执行处理过程,否则对该行不处理。
1.运算
awk 还允许我们执行整数和浮点运算。通过使用数学表达式,可以很方便地编写计算文件中空白行数量的脚本。以下就是这样一个脚本:
awk 'BEGIN { x=0 }/^$/ { x=x+1 }END { print "I found " x " blank lines. " }' 文件名
在 BEGIN 块中,将整数变量 x 初始化成零。然后,awk 每次遇到空白行时,awk 将执行 x=x+1 语句,递增 x。处理完所有行之后,执行 END 块,awk 将打印出最终摘要,指出它找到的空白行数量。
awk 的优点之一就是“简单和字符串化”。我认为 awk 变量“字符串化”是因为所有 awk 变量在内部都是按字符串形式存储的。同时,awk 变量是“简单的”,因为可以对它执行数学操作,如果想要对每个输入行的第一个字段乘方并加一,可以使用以下脚本:
awk { print ($1^2)+1 } 文件
awk 在对数学表达式求值时会将该变量当作数字零处理
awk 的另一个优点是它有完整的数学运算符集合。除了标准的加、减、乘、除,awk 还允许使用前面演示过的指数运算符 "^"、模(余数)运算符 "%" 和其它许多从 C 语言中借入的易于使用的赋值操作符。
这些运算符包括前后加减(i++、--foo)、加/减/乘/除赋值运算符( a+=3、b*=2、c/=2.2、d-=6.2)。不仅如此 -- 我们还有易于使用的模/指数赋值运算符(a^=2、b%=4)。
2. FS 字段分隔符
FS 值并没有被限制为单一字符;可以通过指定任意长度的字符模式,将它设置成规则表达式。如果正在处理由一个或多个 tab 分隔的字段,您可能希望按以下方式设置 FS:
cat file
a b
a c
awk -vFS="\t+" '{print $2}' file
以上示例中,我们使用特殊 "+" 规则表达式字符,它表示“一个或多个前一字符”。
如果字段由空格分隔(一个或多个空格或 tab),您可能想要将 FS 设置成以下规则表达式:
awk FS="[[:space:]+]" '{print $2}' file
3.NF变量(字段总数)
cat file
hello everyone!!
This is egg!!
可以使用 NF 变量来只显示某些输入行:
awk 'NF == 3 { print "this particular record has three fields: " $0 }' file
当然,也可以在条件语句中使用 NF 变量,如下:
awk '{if ( NF > 2 ) {print $1 " " $2 ":" $3}}' file
4.NR变量(当前行数)
例:
awk '{if(NR>10)print "OK,now for the real information!"}' file
如果行数大于10 就打印。。。。
5.RT变量(就是指定的那个分隔符)
例:
echo "111 222|333 444|555 666" |awk 'BEGIN{RS="|"}{print $0,RT}'
RT即是分隔符 |
6.RS变量(记录分隔符,默认分隔符为\n)
例如:
echo "111 222|333 444|555 666"|awk 'BEGIN{RS="|"}{print $0,RT}'
输出结果为:
111 222 |
333 444 |
555 666
也可为正则表达式
echo "111 222a333 444b555 666"|awk 'BEGIN{RS="[a-z]+"}{print $1,RS,RT}'
结果为:
-
111 [a-z]+ a
-
333 [a-z]+ b
-
555 [a-z]+
注:RS为空时,即RS="" awk会自动以多行作为分隔符,即\n\n....
7.ORS变量(记录输出分隔符,默认为\n)
把ORS看成是RS的反过程,更易于理解。
-
[zhangy@localhost test]$ awk 'BEGIN{ORS="\n"}{print $0}' test1
-
111 222
-
333 444
-
555 666
-
[zhangy@localhost test]$ awk 'BEGIN{ORS="|"}{print $0}' test1
-
111 222|333 444|555 666|
8.FS变量与OFS变量
1.FS指定列分隔符
-
[zhangy@localhost test]$ echo "111|222|333"|awk '{print $1}'
-
111|222|333
-
[zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS="|"}{print $1}'
-
111
2.FS也可用正则
-
[zhangy@localhost test]$ echo "111||222|333"|awk 'BEGIN{FS="[|]+"}{print $1}'
-
111
3.FS为空的时候
-
[zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS=""}{NF++;print $0}'
-
1 1 1 | 2 2 2 | 3 3 3
当FS为空的时候,awk会把一行中的每个字符,当成一列来处理。
4.RS被设定成非\n时,\n会成FS分割符中的一个
-
[zhangy@localhost test]$ cat test1
-
111 222
-
333 444
-
555 666
-
[zhangy@localhost test]$ awk 'BEGIN{RS="444";}{print $2,$3}' test1
-
222 333
-
666
222和333之间是有一个\n的,当RS设定成444后,222和333被认定成同一行的二列了,其实按常规思想是二行的一列才对。
5.OFS列输出分隔符
-
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1,$2}' test1
-
111|222
-
333|444
-
555|666
-
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1
-
111|222
-
333|444
-
555|666
test1只有二列,如果100列,都写出来太麻烦了吧。
-
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $0}' test1
-
111 222
-
333 444
-
555 666
-
[zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1
-
111|222
-
333|444
-
555|666
-
-
-
-
为什么第二种方法中的OFS生效呢?个人觉得,awk觉查到列有所变化时,就会让OFS生效,没变化直接输出了。
阅读(1079) | 评论(0) | 转发(0) |