Linux命令 awk


原文链接: Linux命令 awk

Linux强大命令 Awk 20分钟入门介绍

用awk输出某列字符长度大于规定数值的行

awk '{if(length($3)>30)print $0}' urfile

要显示长于 72 个字符的文件的行

awk 'length($0) >72' file

Shell 按照字符串长度进行排序

awk ' { print length, $0}' file.txt | sort -n | sed 's/.* //'
对文件内容按照每行的字符串长度进行排序吗!

awk '{print length($0),$0}' urfile | sort -k1,1nr | cut -d' ' -f2
cat myfile | awk '{print length, $0}' | sort -rn | sed 's/^[0-9]\+ //'

查看nginx连接数命令

netstat -n | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'

多行合并一行空格

awk 'BEGIN{b=0} {if($0==""){b=1;next;} if(b){print "\n"$0;b=0;}else print;}' input >output

cat .bash_history | awk '{print $1}' | sort | uniq -c | sort -nr | head -16

近输出前两行

awk 'NR<3{print $2,$1}' test.md

sudo dpkg -l |awk -F'-' -v OFS='|' '/zip/{print $1,$2}'

-v OFS='|' 指定输出分隔符为|
-F'-' 输入分隔符为 -
/zip/ 查找zip
{}

awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息
awk处理过程: 依次对每一行进行处理,然后输出
awk命令形式:
awk [-F|-f|-v] ‘BEGIN{} //{command1; command2} END{}’ file
[-F|-f|-v] 大参数,-F指定分隔符,-f调用脚本,-v定义变量 var=value
' ' 引用代码块
BEGIN 初始化代码块,在对每一行进行处理之前,初始化代码,主要是引用全局变量,设置FS分隔符
// 匹配代码块,可以是字符串或正则表达式
{} 命令代码块,包含一条或多条命令
; 多条命令使用分号分隔
END 结尾代码块,在对每一行进行处理之后再执行的代码块,主要是进行最终计算或输出结尾摘要信息

特殊要点:

$0 表示整个当前行
$1 每行第一个字段

-F'[:#/]' 定义三个分隔符
NF [字段数] 量变量 number fields
NR [行号] 每行的记录号,多文件记录递增 number line
FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始
FS BEGIN时定义分隔符输入分隔符 默认空白
RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)

-v OFS='|' 指定输出分隔符为|
OFS 输出字段分隔符, 默认也是空格,可以改为制表符等
ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕

\t 制表符
\n 换行符
~ 匹配,与==相比不是精确比较
!~ 不匹配,不精确比较
== 等于,必须全部相等,精确比较
!= 不等于,精确比较
&&  逻辑与
|| 逻辑或

  • 匹配时表示1个或1个以上
    /[0-9][0-9]+/ 两个或两个以上数字
    /[0-9][0-9]* / 一个或一个以上数字
    FILENAME 文件名

参考链接:http://man.linuxde.net/awk

awk是一种编程语言,用于在linux/unix下对文本和数据进行处理。数据可以来自标准输入(stdin)、一个或多个文件,

或其它命令的输出。它支持用户自定义函数和动态正则表达式等先进功能,是linux/unix下的一个强大编程工具。它在命令行
中使用,但更多是作为脚本来使用。awk有很多内建的功能,比如数组、函数等,这是它和C语言的相同之处,灵活性是awk最大的优势。

语法:

awk [options] 'script' var=value file(s)
awk [options] -f scriptfile var=value file(s)

选项:

-F fs   fs指定输入分隔符,fs可以是字符串或正则表达式,如-F:
-v var=value   赋值一个用户定义变量,将外部变量传递给awk
-f scripfile  从脚本文件中读取awk命令 -m[fr] val   对val值设置内在限制,
-mf选项限制分配给val的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。

awk模式和操作:

模式
模式可以是以下任意一个:
    /正则表达式/:使用通配符的扩展集。
    关系表达式:使用运算符进行操作,可以是字符串或数字的比较测试。
    模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
    BEGIN语句块、pattern语句块、END语句块:参见awk的工作原理

操作:
操作由一个或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内,主要部分是:
    变量或数组赋值
    输出命令
    内置函数
    控制流语句

awk脚本基本结构

awk 'BEGIN{ print "start" } pattern{ commands } END{ print "end" }' file
一个awk脚本通常由:BEGIN语句块、能够使用模式匹配的通用语句块、END语句块3部分组成,这三个部分是可选的。

任意一个部分都可以不出现在脚本中,脚本通常是被单引号或双引号中,
例如: awk 'BEGIN{ i=0 } { i++ } END{ print i }' filename awk "BEGIN{ i=0 } { i++ } END{ print i }" filename
awk的工作原理

awk 'BEGIN{ commands } pattern{ commands } END{ commands }'
1、执行BEGIN{ commands }语句块中的语句;
2、从文件或标准输入(stdin)读取一行,然后执行pattern{ commands }语句块,它逐行扫描文件,从第一行到
    最后一行重复这个过程,直到文件全部被读取完毕。
3、当读至输入流末尾时,执行END{ commands }语句块。
BEGIN语句块在awk开始从输入流中读取行之前被执行,这是一个可选的语句块,比如变量初始化、打印输出表格的表头等
    语句通常可以写在BEGIN语句块中。
END语句块在awk从输入流中读取完所有的行之后即被执行,比如打印所有行的分析结果这类信息汇总都是在END语句块中
    完成,它也是一个可选语句块。
pattern语句块中的通用命令是最重要的部分,它也是可选的。如果没有提供pattern语句块,则默认执行{ print },即
    打印每一个读取到的行,awk读取的每一行都会执行该语句块。
示例:
    1)打印当前行
        shell> echo -e "A line 1\nA line 2" | awk 'BEGIN{ print "Start" } { print } END{ print "End" }'
        Start
        A line 1
        A line 2
        End
        当使用不带参数的print时,它就打印当前行,当print的参数是以逗号进行分隔时,打印时则以空格作为定界符。
        在awk的print语句块中双引号是被当作拼接符使用,
    2)参数已逗号分隔
        shell> echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1,var2,var3; }'
        v1 v2 v3
    3)双引号拼接使用
        shell> echo | awk '{ var1="v1"; var2="v2"; var3="v3"; print var1"="var2"="var3; }'
        v1=v2=v3
    { }类似一个循环体,会对文件中的每一行进行迭代,通常变量初始化语句(如:i=0)以及打印文件头部的语句放入
        BEGIN语句块中,将打印的结果等语句放在END语句块中。

awk内置变量(预定义变量):

说明:[A][N][P][G]表示第一个支持变量的工具,[A]=awk、[N]=nawk、[P]=POSIXawk、[G]=gawk
$n 当前记录的第n个字段,比如n为1表示第一个字段,n为2表示第二个字段。
$0 这个变量包含执行过程中当前行的文本内容。
[N] ARGC 命令行参数的数目。
[G] ARGIND 命令行中当前文件的位置(从0开始算)。
[N] ARGV 包含命令行参数的数组。
[G] CONVFMT 数字转换格式(默认值为%.6g)。
[P] ENVIRON 环境变量关联数组。
[N] ERRNO 最后一个系统错误的描述。
[G] FIELDWIDTHS 字段宽度列表(用空格键分隔)。
[A] FILENAME 当前输入文件的名。
[P] FNR 同NR,但相对于当前文件。
[A] FS 字段分隔符(默认是任何空格)。
[G] IGNORECASE 如果为真,则进行忽略大小写的匹配。
[A] NF 表示字段数,在执行过程中对应于当前的字段数。
[A] NR 表示记录数,在执行过程中对应于当前的行号。
[A] OFMT 数字的输出格式(默认值是%.6g)。
[A] OFS 输出字段分隔符(默认值是一个空格)。
[A] ORS 输出记录分隔符(默认值是一个换行符)。
[A] RS 记录分隔符(默认是一个换行符)。
[N] RSTART 由match函数所匹配的字符串的第一个位置。
[N] RLENGTH 由match函数所匹配的字符串的长度。
[N] SUBSEP 数组下标分隔符(默认值是34)。
示例:
1)NR NF使用
    shell> echo -e "line1 f2 f3nline2 f4 f5nline3 f6 f7" | awk '{print "Line No:"NR", No of fields:"NF, "$0="$0, "$1="$1, "$2="$2, "$3="$3}'
    Line No:1, No of fields:3 $0=line1 f2 f3 $1=line1 $2=f2 $3=f3
    Line No:2, No of fields:3 $0=line2 f4 f5 $1=line2 $2=f4 $3=f5
    Line No:3, No of fields:3 $0=line3 f6 f7 $1=line3 $2=f6 $3=f7
2)使用print $NF可以打印出一行中的最后一个字段,使用$(NF-1)则是打印倒数第二个字段,其他以此类推:
    shell> echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $NF}'
    f3 f5
    shell> echo -e "line1 f2 f3n line2 f4 f5" | awk '{print $(NF-1)}'
    f2 f4
3)打印每一行的第二和第三个字段:
    shell> awk '{ print $2,$3 }' filename
4)统计文件中的行数:
    shell> awk 'END{ print NR }' filename
    以上命令只使用了END语句块,在读入每一行的时,awk会将NR更新为对应的行号,当到达最后一行NR的值就是最后一行的行号,所以END语句块中的NR就是文件的行数。
5)一个每一行中第一个字段值累加
    shell> seq 5 | awk 'BEGIN{ sum=0; print "总和:" } { print $1"+"; sum+=$1 } END{ print "等于"; print sum }'
    总和: 1+ 2+ 3+ 4+ 5+ 等于 15

将外部变量值传递给awk

1)借助-v选项,可以将外部值(并非来自stdin)传递给awk
    shell> VAR=1000; echo | awk -v variable=$VAR '{print variable}'
2)另一种传递外部变量方法
    shell> var1="aaa"; var2="bbb"; echo | awk '{print v1, v2}' v1=$var1 v2=$var2
    注:=表示赋值时,前后不要加空格
3)当输入来自于文件时使用
    shell> awk '{ print v1,v2 }' v1=$var1 v2=$var2 filename
以上方法中,变量之间用空格分隔作为awk的命令行参数跟随在BEGIN、{}和END语句块之后。

awk运算与判断

未完,待续

print & $0
print 是awk打印指定内容的主要命令
awk '{print}' /etc/passwd == awk '{print $0}' /etc/passwd
awk '{print " "}' /etc/passwd //不输出passwd的内容,而是输出相同个数的空行,进一步解释了awk是一行一行处理文本
awk '{print "a"}' /etc/passwd //输出相同个数的a行,一行只有一个a字母
awk -F":" '{print $1}' /etc/passwd
awk -F: '{print $1; print $2}' /etc/passwd //将每一行的前二个字段,分行输出,进一步理解一行一行处理文本
awk -F: '{print $1,$3,$6}' OFS="\t" /etc/passwd //输出字段1,3,6,以制表符作为分隔符

-f指定脚本文件
awk -f script.awk file
BEGIN{
FS=":"
}
{print $1} //效果与awk -F":" '{print $1}'相同,只是分隔符使用FS在代码自身中指定

awk 'BEGIN{X=0} /^$/{ X+=1 } END{print "I find",X,"blank lines."}' test
I find 4 blank lines.
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is",sum}' //计算文件大小
total size is 17487

-F指定分隔符
$1 指指定分隔符后,第一个字段,$3第三个字段, \t是制表符
一个或多个连续的空格或制表符看做一个定界符,即多个空格看做一个空格
awk -F":" '{print $1}' /etc/passwd
awk -F":" '{print $1 $3}' /etc/passwd //$1与$3相连输出,不分隔
awk -F":" '{print $1,$3}' /etc/passwd //多了一个逗号,$1与$3使用空格分隔
awk -F":" '{print $1 " " $3}' /etc/passwd //$1与$3之间手动添加空格分隔
awk -F":" '{print "Username:" $1 "\t\t Uid:" $3 }' /etc/passwd //自定义输出
awk -F: '{print NF}' /etc/passwd //显示每行有多少字段
awk -F: '{print $NF}' /etc/passwd //将每行第NF个字段的值打印出来
awk -F: 'NF==4 {print }' /etc/passwd //显示只有4个字段的行
awk -F: 'NF>2{print $0}' /etc/passwd //显示每行字段数量大于2的行
awk '{print NR,$0}' /etc/passwd //输出每行的行号
awk -F: '{print NR,NF,$NF,"\t",$0}' /etc/passwd //依次打印行号,字段数,最后字段值,制表符,每行内容
awk -F: 'NR==5{print}' /etc/passwd //显示第5行
awk -F: 'NR==5 || NR==6{print}' /etc/passwd //显示第5行和第6行
route -n|awk 'NR!=1{print}' //不显示第一行

//匹配代码块
//纯字符匹配 !//纯字符不匹配 ~//字段值匹配 !~//字段值不匹配 ~/a1|a2/字段值匹配a1或a2
awk '/mysql/' /etc/passwd
awk '/mysql/{print }' /etc/passwd
awk '/mysql/{print $0}' /etc/passwd //三条指令结果一样
awk '!/mysql/{print $0}' /etc/passwd //输出不匹配mysql的行
awk '/mysql|mail/{print}' /etc/passwd
awk '!/mysql|mail/{print}' /etc/passwd
awk -F: '/mail/,/mysql/{print}' /etc/passwd //区间匹配
awk '/[2][7][7]*/{print $0}' /etc/passwd //匹配包含27为数字开头的行,如27,277,2777...
awk -F: '$1~/mail/{print $1}' /etc/passwd //$1匹配指定内容才显示
awk -F: '{if($1~/mail/) print $1}' /etc/passwd //与上面相同
awk -F: '$1!~/mail/{print $1}' /etc/passwd //不匹配
awk -F: '$1!~/mail|mysql/{print $1}' /etc/passwd

IF语句
必须用在{}中,且比较内容用()扩起来
awk -F: '{if($1~/mail/) print $1}' /etc/passwd //简写
awk -F: '{if($1~/mail/) {print $1}}' /etc/passwd //全写
awk -F: '{if($1~/mail/) {print $1} else {print $2}}' /etc/passwd //if...else...

条件表达式
== != > >=
awk -F":" '$1=="mysql"{print $3}' /etc/passwd
awk -F":" '{if($1=="mysql") print $3}' /etc/passwd //与上面相同
awk -F":" '$1!="mysql"{print $3}' /etc/passwd //不等于
awk -F":" '$3>1000{print $3}' /etc/passwd //大于
awk -F":" '$3>=100{print $3}' /etc/passwd //大于等于
awk -F":" '$3<1{print $3}' /etc/passwd //小于
awk -F":" '$3<=1{print $3}' /etc/passwd //小于等于

逻辑运算符
&& ||
awk -F: '$1~/mail/ && $3>8 {print }' /etc/passwd //逻辑与,$1匹配mail,并且$3>8
awk -F: '{if($1~/mail/ && $3>8) print }' /etc/passwd
awk -F: '$1~/mail/ || $3>1000 {print }' /etc/passwd //逻辑或
awk -F: '{if($1~/mail/ || $3>1000) print }' /etc/passwd

数值运算
awk -F: '$3 > 100' /etc/passwd
awk -F: '$3 > 100 || $3 < 5' /etc/passwd
awk -F: '$3+$4 > 200' /etc/passwd
awk -F: '/mysql|mail/{print $3+10}' /etc/passwd //第三个字段加10打印
awk -F: '/mysql/{print $3-$4}' /etc/passwd //减法
awk -F: '/mysql/{print $3*$4}' /etc/passwd //求乘积
awk '/MemFree/{print $2/1024}' /proc/meminfo //除法
awk '/MemFree/{print int($2/1024)}' /proc/meminfo //取整

输出分隔符OFS
awk '$6 ~ /FIN/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
awk '$6 ~ /WAIT/ || NR==1 {print NR,$4,$5,$6}' OFS="\t" netstat.txt
//输出字段6匹配WAIT的行,其中输出每行行号,字段4,5,6,并使用制表符分割字段

输出处理结果到文件
①在命令代码块中直接输出 route -n|awk 'NR!=1{print > "./fs"}'
②使用重定向进行输出 route -n|awk 'NR!=1{print}' > ./fs

格式化输出
netstat -anp|awk '{printf "%-8s %-8s %-10s\n",$1,$2,$3}'
printf表示格式输出
%格式化输出分隔符
-8长度为8个字符
s表示字符串类型
打印每行前三个字段,指定第一个字段输出字符串类型(长度为8),第二个字段输出字符串类型(长度为8),
第三个字段输出字符串类型(长度为10)
netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-10s %-10s %-10s \n",$1,$2,$3}'
netstat -anp|awk '$6=="LISTEN" || NR==1 {printf "%-3s %-10s %-10s %-10s \n",NR,$1,$2,$3}'

IF语句
awk -F: '{if($3>100) print "large"; else print "small"}' /etc/passwd
small
small
small
large
small
small
awk -F: 'BEGIN{A=0;B=0} {if($3>100) {A++; print "large"} else {B++; print "small"}} END{print A,"\t",B}' /etc/passwd

                                                                                                              //ID大于100,A加1,否则B加1

awk -F: '{if($3<100) next; else print}' /etc/passwd //小于100跳过,否则显示 awk -F: 'BEGIN{i=1} {if(i100 ? "yes":"no")}' /etc/passwd
awk -F: '{print ($3>100 ? $3":\tyes":$3":\tno")}' /etc/passwd

while语句
awk -F: 'BEGIN{i=1} {while(i<NF) print NF,$i,i++}' /etc/passwd
7 root 1
7 x 2
7 0 3
7 0 4
7 root 5
7 /root 6

数组
netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) print i,"\t",a[i]}'
netstat -anp|awk 'NR!=1{a[$6]++} END{for (i in a) printf "%-20s %-10s %-5s \n", i,"\t",a[i]}'
9523 1
9929 1
LISTEN 6
7903 1
3038/cupsd 1
7913 1
10837 1
9833 1

应用1
awk -F: '{print NF}' helloworld.sh //输出文件每行有多少字段
awk -F: '{print $1,$2,$3,$4,$5}' helloworld.sh //输出前5个字段
awk -F: '{print $1,$2,$3,$4,$5}' OFS='\t' helloworld.sh //输出前5个字段并使用制表符分隔输出
awk -F: '{print NR,$1,$2,$3,$4,$5}' OFS='\t' helloworld.sh //制表符分隔输出前5个字段,并打印行号

应用2
awk -F'[:#]' '{print NF}' helloworld.sh //指定多个分隔符: #,输出每行多少字段
awk -F'[:#]' '{print $1,$2,$3,$4,$5,$6,$7}' OFS='\t' helloworld.sh //制表符分隔输出多字段

应用3
awk -F'[:#/]' '{print NF}' helloworld.sh //指定三个分隔符,并输出每行字段数
awk -F'[:#/]' '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12}' helloworld.sh //制表符分隔输出多字段

应用4
计算/home目录下,普通文件的大小,使用KB作为单位
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",sum/1024,"KB"}'
ls -l|awk 'BEGIN{sum=0} !/^d/{sum+=$5} END{print "total size is:",int(sum/1024),"KB"}' //int是取整的意思

应用5
统计netstat -anp 状态为LISTEN和CONNECT的连接数量分别是多少
netstat -anp|awk '$6~/LISTEN|CONNECTED/{sum[$6]++} END{for (i in sum) printf "%-10s %-6s %-3s \n", i," ",sum[i]}'

应用6
统计/home目录下不同用户的普通文件的总数是多少?
ls -l|awk 'NR!=1 && !/^d/{sum[$3]++} END{for (i in sum) printf "%-6s %-5s %-3s \n",i," ",sum[i]}'
mysql 199
root 374
统计/home目录下不同用户的普通文件的大小总size是多少?
ls -l|awk 'NR!=1 && !/^d/{sum[$3]+=$5} END{for (i in sum) printf "%-6s %-5s %-3s %-2s \n",i," ",sum[i]/1024/1024,"MB"}'

应用7
输出成绩表
awk 'BEGIN{math=0;eng=0;com=0;printf "Lineno. Name No. Math English Computer Total\n";printf "------------------------------------------------------------\n"}{math+=$3; eng+=$4; com+=$5;printf "%-8s %-7s %-7s %-7s %-9s %-10s %-7s \n",NR,$1,$2,$3,$4,$5,$3+$4+$5} END{printf "------------------------------------------------------------\n";printf "%-24s %-7s %-9s %-20s \n","Total:",math,eng,com;printf "%-24s %-7s %-9s %-20s \n","Avg:",math/NR,eng/NR,com/NR}' test0

[root@localhost home]# cat test0
Marry 2143 78 84 77
Jack 2321 66 78 45
Tom 2122 48 77 71
Mike 2537 87 97 95
Bob 2415 40 57 62

awk手册
http://www.chinaunix.net/old_jh/7/16985.html

Awk小技巧

1.
BEGIN和END的作用
BEGIN
代码块:在处理文本之前,一般用于初始化的
主体代码块:对文本的每一行
END
代码块:在处理完文本之后,一般用于汇总数据打印结果
2.
怎样打印文本的每一行
cat num.txt |awk '{print $0}'
cat num.txt |awk '{print}'
cat num.txt |awk '1{print}' #非0为真,0为假
cat num.txt |awk '1'

  1. 常用内置变量有哪些
    NR:当前行数
    NF:当前列数
    ORS:输出行分隔符
    OFS:输出列分隔符

4.
怎么在整个文本最开始插入一行
cat num.txt |sed '1i00'
cat num.txt|awk 'BEGIN{print "00"}1'
5.
怎样只打印某一些行
awk 'NR>=3&&NR<=5{print $0}'
cat num.txt |awk 'NR==3,NR==5'
cat num.txt |awk '/3/,/5/'
cat num.txt |awk '$NF=="d",$NF=="g"'
cat a1.txt|awk '/1{print $5}'
ifconfig|awk -F' +|:' '/inet /{print $4}'
9.
替换分隔符
df|awk '{$1=$1;OFS=":";print}'

10.
将一列变为多列
awk 'ORS=NR%3?" ":"\n"'
问号表达式
变量=表达式?值1(为真): 值2(为假)

11.
多文件操作怎样实现
awk 'FNR==NR{k[$1]}FNR!=NR{if($1 in k){print}}' uid.txt num.txt
awk 'FILENAME=="uid.txt"{k[$1]}FILENAME=="num.txt"{if($1 in k){print}}' uid.txt num.txt

12.
多压缩文件的操作
mkfifo num.fifo
mkfifo uid.fifo
zcat num.txt.gz > num.fifo &
zcat uid.txt.gz > uid.fifo &
awk 'FNR==NR{k[$1]}FNR!=NR{if($1 in k){print}}' uid.fifo num.fifo

13.
Awk 的脚本想改写成perl困难吗
A2p abc.awk > abc.pl

14.
Awk 怎么对文件进行切分
cat text1.txt |awk '{print > "log/file_"int((NR-1)/10000)".txt"}'

15.
在awk中怎么调用其他语言

cat num.txt |awk '{cmd="date +%s";cmd|getline time;close(cmd);print $0,time}'

16.
Awk和shell相互传值
Shell传给awk
b=123
awk -v a=$b 'BEGIN{print a}'
awk 'BEGIN{a='"$b"';print a}'
awk传给shell
eval awk 'BEGIN{print "a=555;b=666"}'

17.
用awk来写mapreduce
Map.sh: awk '{sum[$1]++}END{for(i in sum){print i,sum[i]}}'
Red.sh: awk '{sum[$1]+=$2}END{for(i in sum){print i,sum[i]}}'
/usr/local/hadoop-0.20.2/bin/hadoop jar
/usr/local/hadoop-0.20.2/contrib/streaming/hadoop-0.20.2-streaming.jar -jobconf
mapred.reduce.tasks=1 -jobconf mapred.textoutputformat.separator=" " -jobconf
stream.map.output.field.separator=" " -mapper /root/map.sh -file /root/map.sh -reducer
/root/red.sh -file /root/red.sh -input /user/root/in1 -output /user/root/out1

RS:Record Separator,记录分隔符

ORS:Output Record Separate,输出当前记录分隔符

FS:Field Separator,字段分隔符

OFS:Out of Field Separator,输出字段分隔符

PS:RS、ORS、FS、OFS的英文解释绝不是这样的,这里只是解释清楚。建议去阅读awk的英文读物,其中解释了缩写的含义。

什么是field(字段),什么是record(记录行)?

示例:

1.txt

i am a student.
i like to swim
hello moto
1代表第一个记录行,2代表第二个记录行,3代表第三个记录行。通过观察我们可以知道总共有3个记录行(record)。

看看第一行:“i am a student”,这一行的每个单词都是一个字段(field)。“i”是一个字段,“am”是一个字段,“a”是一个字段,“student”是一个字段,该行总共有4个字段。

RS与ORS

RS:记录行分隔符

示例:

1.txt

a\n
b\n
c\n
d\n
e\n
该文本总共有5行,每一行都有一个换行符“\n”。所以每行记录都是以“\n”为一个(换行的)标志。

可以用一下方法来理解:

找到某某标志,让每个某某后的内容重新变成一行

示例

1.txt

a|b|c

代码:awk 'BEGIN{ RS="|"; } { print $0 }'

a

b

b

ORS:可以看成RS的逆向过程

示例

1.txt

a

b

c

可以这样理解:

观察每一行的“换行符号”,然后将“换行符号”替换成你想要的符号。

awk 'BEGIN{ ORS="----" }{ print $0 }' 1.txt

a----b----c----

FS:字段分隔符

FS默认值为“ (空格)”,如“hello moto”.

在“hello moto”中有一个空格,空格就是hello与moto的分隔符(separator),而hello与moto就为字段(files)。awk以空格来区分。

在看看“i----love----you”,如果我们用命令“awk “{ print $1 }””会看到结果为:

i----love----you

如果想打印出三个字母,通过观察可发现“----”为分隔符。

awk 'BEGIN{ FS="----";}{ print $1,$2,$3 }' filename

i love you

OFS:输出的字段分隔符。

这么解释吧,如上例中“i----love----you”,“----”为分隔符(FS),如果我们想改为用其他符号显示可以这样:

awk 'BEGIN{ FS="----";OFS="*****" }{ print $1,$2,$3 }' filename

i**love**you

其实OFS还有一个例子
echo "abc" | awk '{ OFS="." } { NF=NF; print NF,$0}'
结果
1.abc

PS:RS与ORS可以说成是一个互逆的过程(↔)也可以看成一个替换的过程,但是看成互逆的过程比较好理解;FS与OFS就是一个替换的过程。

`