Chinaunix首页 | 论坛 | 博客
  • 博客访问: 592966
  • 博文数量: 118
  • 博客积分: 2114
  • 博客等级: 大尉
  • 技术积分: 1275
  • 用 户 组: 普通用户
  • 注册时间: 2009-03-10 00:02
文章分类

全部博文(118)

文章存档

2019年(1)

2018年(4)

2017年(1)

2016年(6)

2015年(1)

2014年(1)

2013年(5)

2012年(4)

2011年(17)

2010年(13)

2009年(65)

分类: LINUX

2017-02-09 15:37:07

awk中 FS、NF、NR、RT、RS、ORS、OFS用法 

分类: LINUX

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}' 
结果为:
  1. 111 [a-z]+ a  
  2.  333 [a-z]+ b  
  3.  555 [a-z]+  

注:RS为空时,即RS=""   awk会自动以多行作为分隔符,即\n\n....

7.ORS变量(记录输出分隔符,默认为\n
把ORS看成是RS的反过程,更易于理解。
  1. [zhangy@localhost test]$ awk 'BEGIN{ORS="\n"}{print $0}' test1  //awk '{print $0}' test1二者是一样的  
  2. 111 222  
  3. 333 444  
  4. 555 666  
  5. [zhangy@localhost test]$ awk 'BEGIN{ORS="|"}{print $0}' test1  
  6. 111 222|333 444|555 666|  

8.FS变量与OFS变量
1.FS指定列分隔符
  1. [zhangy@localhost test]$ echo "111|222|333"|awk '{print $1}'  
  2.  111|222|333  
  3. [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS="|"}{print $1}'  
  4.  111  
2.FS也可用正则
  1. [zhangy@localhost test]$ echo "111||222|333"|awk 'BEGIN{FS="[|]+"}{print $1}'  
  2. 111  
3.FS为空的时候
  1. [zhangy@localhost test]$ echo "111|222|333"|awk 'BEGIN{FS=""}{NF++;print $0}'  
  2. 1 1 1 | 2 2 2 | 3 3 3  
当FS为空的时候,awk会把一行中的每个字符,当成一列来处理
4.RS被设定成非\n时,\n会成FS分割符中的一个
  1. [zhangy@localhost test]$ cat test1  
  2.  111 222  
  3.  333 444  
  4.  555 666  
  5. [zhangy@localhost test]$ awk 'BEGIN{RS="444";}{print $2,$3}' test1  
  6.  222 333  
  7.  666  
222和333之间是有一个\n的,当RS设定成444后,222和333被认定成同一行的二列了,其实按常规思想是二行的一列才对

5.OFS列输出分隔符
  1. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1,$2}' test1  
  2.  111|222  
  3.  333|444  
  4.  555|666  
  5. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $1 OFS $2}' test1  
  6.  111|222  
  7.  333|444  
  8.  555|666  
test1只有二列,如果100列,都写出来太麻烦了吧。
  1. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{print $0}' test1  
  2.  111 222  
  3.  333 444  
  4.  555 666  
  5. [zhangy@localhost test]$ awk 'BEGIN{OFS="|";}{NF=NF;print $0}' test1  
  6.  111|222  
  7.  333|444  
  8.  555|666  



  9. 为什么第二种方法中的OFS生效呢?个人觉得,awk觉查到列有所变化时,就会让OFS生效,没变化直接输出了。
阅读(1085) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~