"模仿"对咱们做程序的来说是最擅长的了,咱们先来一段实战,然后再学习枯燥的理论,我想这样学习起来会轻松一些.^_^
1.基础数据(student.txt)
序号 姓名 年龄 地址
1 tom 20 BJ
2 Jack 19 HN
3 Jone 21 BJ
4 Zhang 20 HK
说明:第一行的"序号"等,只是帮助说明,不在文件中.
2.统计出各个地址有多少人
命令:
awk '{print $4}' student.txt|sort |uniq -c |sort -rn |more
结果:
2 BJ
1 HN
1 HK
3.显示出序号大于2的记录
命令:
awk '($1>2){print }' student.txt
结果:
3 Jone 21 BJ
4 Zhang 20 HK
4.显示出名称中含有"a"或"t"的记录(注意:此处区分大小写)
命令:
awk '$2~/a|t/{print}' student.txt
结果:
1 tom 20 BJ
2 Jack 19 HN
4 Zhang 20 HK
5.显示出地址等于"BJ"或年龄>=20的记录
命令:
awk '($4~/BJ/ || $3>=20){print}' student.txt
结果:
1 tom 20 BJ
3 Jone 21 BJ
4 Zhang 20 HK
6.把序号大于2的记录显示出来.显示的格式为:序号 姓名 年龄 序号+年龄 序号+姓名 姓名+地址
命令:
awk '($1>2){print $1,$2,$3,$1+$3,$1+$2,$2+$4}' student.txt
结果:
3 Jone 21 24 3 0
4 Zhang 20 24 4 0
说明:
从结果上看,"序号+姓名"并不是我们想像中的两个字符串相加,由此可见awk只能进行数学运算.如果要进行字符的操作,只有使用函数了
7.找出地址是"BJ"的,但姓名中不含"t"的记录
命令:
awk '($2!~/t/ && $4~/BJ/)' student.txt
结果:
3 Jone 21 BJ
awk学习笔记
(本文内容全部来源于网络)
一、awk简介
awk是一种编程语言,主要用于union/linux下的文本和数据处理。它在命令行中使用,但更多是当作脚本使用。gawk是awk的GNU版本,它对awk进行了扩展。
二、语法
(一)命令
1.形式
awk [options] ‘{pattern + action}’ {filenames}
其中 pattern 表示 AWK 在数据中查找的内容,而 action 是在找到匹配内容时所执行的一系列命令。花括号 ({}) 不需要在程序中始终出现,但它们用于根据特定的模式对一系列指令进行分组。
2. 选项
-F fs or --field-separator fs
指定输入文件折分隔符,fs是一个字符串或者是一个正则表达式,如-F:。
-v var=value or --asign var=value
赋值一个用户定义变量。
-f scripfile or --file scriptfile
从脚本文件中读取awk命令。
-mf nnn and -mr nnn
对nnn值设置内在限制,-mf选项限制分配给nnn的最大块数目;-mr选项限制记录的最大数目。这两个功能是Bell实验室版awk的扩展功能,在标准awk中不适用。
-W compact or --compat, -W traditional or --traditional
在兼容模式下运行awk。所以gawk的行为和标准的awk完全一样,所有的awk扩展都被忽略。
-W copyleft or --copyleft, -W copyright or --copyright
打印简短的版权信息。
-W help or --help, -W usage or --usage
打印全部awk选项和每个选项的简短说明。
-W lint or --lint
打印不能向传统unix平台移植的结构的警告。
-W lint-old or --lint-old
打印关于不能向传统unix平台移植的结构的警告。
-W posix
打开兼容模式。但有以下限制,不识别:/x、函数关键字、func、换码序列以及当fs是一个空格时,将新行作为一个域分隔符;操作符**和**=不能代替^和^=;fflush无效。
-W re-interval or --re-inerval
允许间隔正则表达式的使用,参考(grep中的Posix字符类),如括号表达式[[:alpha:]]。
-W source program-text or --source program-text
使用program-text作为源代码,可与-f命令混用。
-W version or --version
打印bug报告信息的版本。
3.模式
模式可以是以下任意一个:
(1)/正则表达式/:使用通配符的扩展集。
(2)关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。
(3)模式匹配表达式:用运算符~(匹配)和~!(不匹配)。
(4)模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。
(5)BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。
(6)END:让用户在最后一条输入记录被读取之后发生的动作。
4.action
操作由一人或多个命令、函数、表达式组成,之间由换行符或分号隔开,并位于大括号内。主要有四部份:
(1)变量或数组赋值
(2)输出命令
(3)内置函数
(4)控制流命令
(二)记录与字段
1.定义
awk将每一行作为一条记录,将每条记录按分割条件进行分割后的一域叫字段。整条记录表示为$0, 第一个字段$1,第二个字段$2……
2.分隔符
默认情况下将制表符和空格都看作字段分隔符(多个空格仍然作为一个分隔符),但是可以将分隔符从空格改为任何其它字符。
有两种方法可通知 AWK 使用新的字段分隔符:使用命令行参数 -F ,或在程序中指定变量 FS。两种方法的效果相同,只有一种例外情况,如下例所示:
$ awk ‘{FS=”:”}{print $2}’ 1.txt
$ awk -F: ‘{print $2}’ 1.txt
$ awk -F”:” ‘{OFS=”-”}{print $1,$2,$3,$4,$5}’ 1.txt
(三)可以使用的特殊字符
- /n (换行)
- /t (制表)
- /b (退格)
- /f (进纸)
- /r (回车)
(四) 引号
单引号只用于区别命令行中的命令与文件名称。
(五)printf命令的各种规格
下表列出 printf 命令提供的各种规格。
规格 | 说明 |
%c | 打印单个 ASCII 字符 |
%d | 打印十进制数 |
%e | 打印数字的科学计数表示 |
%f | 打印浮点表示 |
%g | 打印 %e 或 %f ;两种方式都更简短 |
%o | 打印无符号的八进制数 |
s | 打印 ASCII 字符串 |
%x | 打印无符号的十六进制数 |
%% | 打印百分号;不执行转换 |
可以在 % 与字符之间提供某些附加的格式化参数。这些参数进一步改进数值的打印方式:
参数 | 说明 |
- | 将字段中的表达式向左对齐 |
,width | 根据需要将字段补齐到指定宽度(前导零使用零将字段补齐) |
.prec | 小数点右面数字的最大字符串宽度或最大数量 |
(六)运算符
运算符 | 描述 |
= += -= *= /= %= ^= **= | 赋值 |
?: | C条件表达式 |
|| | 逻辑或 |
&& | 逻辑与 |
~ ~! | 匹配正则表达式和不匹配正则表达式 |
< <= > >= != == | 关系运算符 |
空格 | 连接 |
+ - | 加,减 |
* / & | 乘,除与求余 |
+ - ! | 一元加,减和逻辑非 |
^ *** | 求幂 |
++ -- | 增加或减少,作为前缀或后缀 |
$ | 字段引用 |
in | 数组成员 |
(七)环境变量
变量 | 描述 |
$n | 当前记录的第n个字段,字段间由FS分隔。 |
$0 | 完整的输入记录。 |
ARGC | 命令行参数的数目。 |
ARGIND | 命令行中当前文件的位置(从0开始算)。 |
ARGV | 包含命令行参数的数组。 |
CONVFMT | 数字转换格式(默认值为%. 6g ) |
ENVIRON | 环境变量关联数组。 |
ERRNO | 最后一个系统错误的描述。 |
FIELDWIDTHS | 字段宽度列表(用空格键分隔)。 |
FILENAME | 当前文件名。 |
FNR | 同NR,但相对于当前文件。 |
FS | 字段分隔符(默认是任何空格)。 |
IGNORECASE | 如果为真,则进行忽略大小写的匹配。 |
NF | 当前记录中的字段数。 |
NR | 当前记录数。 |
OFMT | 数字的输出格式(默认值是%. 6g )。 |
OFS | 输出字段分隔符(默认值是一个空格)。 |
ORS | 输出记录分隔符(默认值是一个换行符)。 |
RLENGTH | 由match函数所匹配的字符串的长度。 |
RS | 记录分隔符(默认是一个换行符)。 |
RSTART | 由match函数所匹配的字符串的第一个位置。 |
SUBSEP | 数组下标分隔符(默认值是/034)。 |
(八)条件语句
1.if语句
格式:
{if (expression){
statement; statement; ...
}
}
$ awk '{if ($1 <$2) print $2 "too high"}' test。如果第一个域小于第二个域则打印。
$ awk '{if ($1 < $2) {count++; print "ok"}}' test.如果第一个域小于第二个域,则count加1,并打印ok。
2. if/else语句,用于双重判断
格式:
{if (expression){
statement; statement; ...
}else{
statement; statement; ...
}
}
$ awk '{if ($1 > 100) print $1 "bad" ; else print "ok"}' test。如果$1大于100则打印$1 bad,否则打印ok。
$ awk '{if ($1 > 100){ count++; print $1} else {count--; print $2}' test。如果$1大于100,则count加1,并打印$1,否则count减一,并打印$1。
3. if/else else if语句,用于多重判断
格式:
{if (expression){
statement; statement; ...
} else if (expression){
statement; statement; ...
} else if (expression){
statement; statement; ...
} else {
statement; statement; ...
}
}
(九)循环
awk有三种循环:while循环;for循环;special for循环。
$ awk '{ i = 1; while ( i <= NF ) { print NF,$i; i++}}' test。变量的初始值为1,若i小于可等于NF(记录中域的个数),则执行打印语句,且i增加1。直到i的值大于NF.
$ awk '{for (i = 1; i<NF; i++) print NF,$i}' test。作用同上。
breadkcontinue语句。break用于在满足条件的情况下跳出循环;continue用于在满足条件的情况下忽略后面的语句,直接返回循环的顶端。如:
{for ( x=3; x<=NF; x++)
if ($x<0){print "Bottomed out!"; break}}
{for ( x=3; x<=NF; x++)
if ($x==0){print "Get next item"; continue}}
next语句从输入文件中读取一行,然后从头开始执行awk脚本。如:
{if ($1 ~/test/){next}
else {print}
}
exit语句用于结束awk程序,但不会略过END块。退出状态为0代表成功,非零值表示出错。
(10)数组
awk中的数组的下标可以是数字和字母,称为关联数组。
用变量作为数组下标。如:$ awk {name[x++]=$2};END{for(i=0;i<NR;i++) print i,name[i]}' test。数组name中的下标是一个自定义变量x,awk初始化x的值为0,在每次使用后增加1。第二个域的值被赋给name数组的各个元素。在END模块中,for循环被用于循环整个数组,从下标为0的元素开始,打印那些存储在数组中的值。因为下标是关健字,所以它不一定从0开始,可以从任何值开始。
special for循环用于读取关联数组中的元素。格式如下:
{for (item in arrayname){
print arrayname[item]
}
}
$ awk '/^tom/{name[NR]=$1}; END{for(i in name){print name[i]}}' test。打印有值的数组元素。打印的顺序是随机的。
用字符串作为下标。如:count["test"]
用域值作为数组的下标。一种新的for循环方式,for (index_value in array) statement。如:$ awk '{count[$1]++} END{for(name in count) print name,count[name]}' test。该语句将打印$1中字符串出现的次数。它首先以第一个域作数组count的下标,第一个域变化,索引就变化。
delete函数用于删除数组元素。如:$ awk '{line[x++]=$1} END{for(x in line) delete(line[x])}' test。分配给数组line的是第一个域的值,所有记录处理完成后,special for循环将删除每一个元素。
(11)内建函数
1.字符串函数
(1)sub函数
将2.txt中的IN换成test并输出:
# awk '{sub(/IN/,"test");print}' 2.txt
(2)gsub函数
作用如sub,但它在整个文档中进行匹配。格式如下:
gsub (regular expression, substitution string)
gsub (regular expression, substitution string, target string)
实例:
awk '{gsub(/IN/,"test");print}' 2.txt
(3)index函数
作用:找到第2个字符串在第1个字符串的位置。从1开始,0表示不匹配
实例:awk '{print index("mytest","test") }' 2.txt //输出结果为3
(4)length函数
作用:返回记录的字符数。
实例:
$ awk '{ print length( "test" ) }' 2.txt //打印出“test”的字符串长度。结果为4
$ awk '{ print length }' 2.txt //打印出2.txt中每一行的字符长度
(5)substr函数
作用:截取字符串
实例:
awk '{print substr("mytest",3,4)} ' 2.txt //结果“test”
(6)match函数
作用:match函数返回在字符串中符合正则表达式的起始位置,如果找不到指定的正则表达式则返回0。match函数会设置内建变量RSTART为字符串中子字符串的开始位置,RLENGTH为到子字符串末尾的字符个数。substr可利于这些变量来截取字符串。
实例:
$ awk '{start=match("this is a test",/[a-z]+$/); print start}'
$ awk '{start=match("this is a test",/[a-z]+$/); print start, RSTART, RLENGTH }'
第1例:打印以连续小写字符结尾的开始位置。结果11
第2例:还打印RSTART和RLENGTH变量,这里是11(start),11(RSTART),4(RLENGTH)
(7)toupper和tolower
作用:大小写转换
实例:
$ awk '{ print toupper("test"), tolower("TEST") }' //结果:TEST test
(8)split函数
作用:按一个字符串分割成一个数组
实例:
awk '{split("20:18:00",time,":"); print time[2]}' //结果:18
2.时间函数
(1)systeim()
作用:返回从 1970年 1月 1日 开始到当前时间(不计闰年)的整秒数
实例:
$ awk '{ now = systime(); print now }'
(2)strftime函数
作用:使用C库中的strftime函数格式化时间
实例:
$ awk '{ now=strftime( "%D", systime() ); print now }'
日期和时间格式说明:
格式 | 描述 |
%a | 星期几的缩写(Sun) |
%A | 星期几的完整写法(Sunday) |
%b | 月名的缩写(Oct) |
%B | 月名的完整写法(October) |
%c | 本地日期和时间 |
%d | 十进制日期 |
%D | 日期 08/20/99 |
%e | 日期,如果只有一位会补上一个空格 |
%H | 用十进制表示24小时格式的小时 |
%I | 用十进制表示12小时格式的小时 |
%j | 从 1月 1日起 一年中的第几天 |
%m | 十进制表示的月份 |
%M | 十进制表示的分钟 |
%p | 12小时表示法(AM/PM) |
%S | 十进制表示的秒 |
%U | 十进制表示的一年中的第几个星期(星期天作为一个星期的开始) |
%w | 十进制表示的星期几(星期天是0) |
%W | 十进制表示的一年中的第几个星期(星期一作为一个星期的开始) |
%x | 重新设置本地日期( 08/20/99 ) |
%X | 重新设置本地时间(12:00:00) |
%y | 两位数字表示的年(99) |
%Y | 当前月份 |
%Z | 时区(PDT) |
%% | 百分号(%) |
3.内建数学函数
函数名称 | 返回值 |
atan2(x,y) | y,x范围内的余切 |
cos(x) | 余弦函数 |
exp(x) | 求幂 |
int(x) | 取整 |
log(x) | 自然对数 |
rand() | 随机数 |
sin(x) | 正弦 |
sqrt(x) | 平方根 |
srand(x) | x是rand()函数的种子 |
int(x) | 取整,过程没有舍入 |
rand() | 产生一个大于等于0而小于1的随机数 |
4.自定义函数
格式如下:
function name ( parameter, parameter, parameter, ... ) {
statements
return expression # the return statement and expression are optional
}
三、实操
(一)基本数据(1.txt)
46012 DULANEY EVAN MOBILE AL
46013 DURHAM JEFF MOBILE AL
46015 STEEN BILL MOBILE AL
46017 FELDMAN EVAN MOBILE AL
46018 SWIM STEVE UNKNOWN AL
46019 BOGUE ROBERT PHOENIX AZ
46021 JUNE MICAH PHOENIX AZ
46022 KANE SHERYL UNKNOWN AR
46024 WOOD WILLIAM MUNCIE IN
46026 FERGUS SARAH MUNCIE IN
46027 BUCK SARAH MUNCIE IN
46029 TUTTLE BOB MUNCIE IN
(二)练习
1. awk ‘{print $1,$2,$3,$4,$5}’
46012 DULANEY EVAN MOBILE AL
46013 DURHAM JEFF MOBILE AL
46015 STEEN BILL MOBILE AL
46017 FELDMAN EVAN MOBILE AL
46018 SWIM STEVE UNKNOWN AL
46019 BOGUE ROBERT PHOENIX AZ
46021 JUNE MICAH PHOENIX AZ
46022 KANE SHERYL UNKNOWN AR
46024 WOOD WILLIAM MUNCIE IN
46026 FERGUS SARAH MUNCIE IN
46027 BUCK SARAH MUNCIE IN
46029 TUTTLE BOB MUNCIE IN
2. $ awk ‘{print $2,$3}’
DULANEY EVAN
DURHAM JEFF
STEEN BILL
FELDMAN EVAN
SWIM STEVE
BOGUE ROBERT
JUNE MICAH
KANE SHERYL
WOOD WILLIAM
FERGUS SARAH
BUCK SARAH
TUTTLE BOB
3.使用模式
通过使用模式,你可以只对符合条件的记录进行操作。
(1)$ awk ‘/AL/ {print $3,$2}’ 1.txt
EVAN DULANEY
JEFF DURHAM
BILL STEEN
EVAN FELDMAN
STEVE SWIM
说明:如果不指定字段,则会打印出所有字段:$ awk ‘/AL/’ 1.txt
(2) 对同一数据集的多个命令可以用分号 ( ; ) 分隔开。例如,在一行中打印姓名,而在另一行中打印城市和州名:
$ awk ‘/AL/ {print $3,$2 ; print $4,$5}’
如果分别给出两个打印语句,则会产生完全不同的结果:
$ awk ‘/AL/ {print $3,$2} {print $4,$5}’ 1.txt
只有在列表中找到 AL 时才会给出字段三和字段二。但是,字段四和字段五是无条件的,始终打印它们。只有第一组花括号中的命令对前面紧邻的命令 ( /AL/ ) 起作用。
(3) 在城市与州之间插入一个空格和逗号。然后,在每两行显示之后放置一个空行:
$ awk ‘/AL/ {print $3,$2 ; print $4″, “$5″/n”}’ 1.txt
(4)搜索含有AL或IN的行
$ awk ‘/AL|IN/’ 1.txt
(5)每行的第5个字段含有AL的字符
$ awk ‘$5 ~ /AR/’ 1.txt
(6) 代字号(表示匹配)的对应符号是一个前面带有感叹号的代字号 (!?) 。这些字符通知程序,如果搜索序列没有出现在指定字段中,则找出与搜索序列相匹配的所有行:
$ awk ‘$5 !~ /AR/’ 1.txt
说明:其中是找第5个字段中不含有AR的行
(7) 花括号和字段分隔符
$ awk ‘{print $3,$2}’ 1.txt 与 $ awk ‘{print $3}{print $2}’ names的区别
第1个是将字段3与字段2打印在一行,第2个是将字段3与字段2打印在不同的行。
(8)以冒号分隔,并打印序号
$ awk -F”:” ‘{print NR,$1,$2,$3}’ 1.txt
(9) 找出员工号码处于 46012 和 46015 之间的所有行:
$ awk -F”:” ‘/4601[2-5]/’ 1.txt
4.添加文本
(1) 要将分隔符从空格改为冒号,则命令是
awk ‘{print $1″:”$2″:”$3″:”$4″:”$5}’ 1.txt >2.txt //会生成一个新文件2.txt
(2)找出第5个字段有AL的,并打印相关信息
$ awk ‘$5 ~ /AL/ {print “NAME: “$2″, “$3″/nCITY-STATE: “$4″, “$5″/n”}’ 1.txt
5.数学操作
AWK 除了提供文本功能,还提供全部范围的算术操作符,包括以下符号:
+ 将数字相加 - 减 * 乘 / 除 ^ 执行指数运算 % 提供模 ++ 将变量值加一 += 将其他操作的结果分配给变量 — 将变量减一 -= 将减法操作的结果分配给变量 *= 分配乘法操作的结果 /= 分配除法操作的结果 %= 分配求模操作的结果
(1)打印出第2项与第3项的乘积(此例省略了很多东西)
$ awk ‘{print $1,”QTY: “$2,”PRICE: “$3,”TOTAL: “$2*$3}’ 3.txt
6. BEGIN 和 END
使用 BEGIN 和 END 语句可以分别指定在处理实际开始之前或者完成之后进行操作。 BEGIN 语句最常用于建立变量或显示标题。END不匹配任何的输入文件,但是执行动作块中的所有动作,它在整个输入文件处理完成后被执行。
7. 输入、输出和源文件
AWK 工具可以从文件中读取其输入,正如在此之前所有示例所做的那样,它也可以从其他命令的输出中获取输入。例如:
$ sort emp_names | awk ‘{print $3,$2}’
(1)输入行号和第一个字段,到file2中。
$ awk ‘{print NR, $1 ) > “/tmp/filez” }’ emp_names
说明:> 在不存在文件时创建文件,而/>> 追加到现有文件的尾部
8. 重定向和管道
(1)awk可使用shell的重定向符进行重定向输出,如:$ awk '$1 = 100 {print $1 > "output_file" }' test。上式表示如果第一个域的值等于100,则把它输出到output_file中。也可以用>>来重定向输出,但不清空文件,只做追加操作。
(2)输 出重定向需用到getline函数。getline从标准输入、管道或者当前正在处理的文件之外的其他输入文件获得输入。它负责从输入获得下一行的内容, 并给NF,NR和FNR等内建变量赋值。如果得到一条记录,getline函数返回1,如果到达文件的末尾就返回0,如果出现错误,例如打开文件失败,就 返回-1。如:
$ awk 'BEGIN{ "date" | getline d; print d}' test。执行linux的date命令,并通过管道输出给getline,然后再把输出赋值给自定义变量d,并打印它。
$ awk 'BEGIN{"date" | getline d; split(d,mon); print mon[2]}' test。执行shell的date命令,并通过管道输出给getline,然后getline从管道中读取并将输入赋值给d,split函数把变量d转 化成数组mon,然后打印数组mon的第二个元素。
$ awk 'BEGIN{while( "ls" | getline) print}',命令ls的输出传递给geline作为输入,循环使getline从ls的输出中读取一行,并把它打印到屏幕。这里没有输入文件,因为 BEGIN块在打开输入文件前执行,所以可以忽略输入文件。
$ awk 'BEGIN{printf "What is your name?"; getline name < "/dev/tty" } $1 ~name {print "Found" name on line ", NR "."} END{print "See you," name "."} test。在屏幕上打印”What is your name?",并等待用户应答。当一行输入完毕后,getline函数从终端接收该行输入,并把它储存在自定义变量name中。如果第一个域匹配变量 name的值,print函数就被执行,END块打印See you和name的值。
$ awk 'BEGIN{while (getline < "/etc/passwd" > 0) lc++; print lc}'。awk将 逐行读取文件/etc/passwd的内容,在到达文件末尾前,计数器lc一直增加,当到末尾时,打印lc的值。注意,如果文件不存在,getline返 回-1,如果到达文件的末尾就返回0,如果读到一行,就返回1,所以命令 while (getline < "/etc/passwd")在文件不存在的情况下将陷入无限循环,因为返回-1表示逻辑真。
(3) 可以在awk中打开一个管道,且同一时刻只能有一个管道存在。通过close()可关闭管道。如:$ awk '{print $1, $2 | "sort" }' test END {close("sort")}。awd把print语句的输出通过管道作为linux命令sort的输入,END块执行关闭管道操作。
(4) system函数可以在awk中执行linux的命令。如:$ awk 'BEGIN{system("clear")'。
(5) fflush函数用以刷新输出缓冲区,如果没有参数,就刷新标准输出的缓冲区,如果以空字符串为参数,如fflush(""),则刷新所有文件和管道的输出缓冲区。
四、处理错误
AWK 工具报告所发生错误的方式很令人恼火。一个错误会阻碍任何操作的进行,所提供的错误信息非常含混不清:
awk: syntax error near line 2
awk: bailing out near line 2
您可能会花几小时的时间查看第 2 行,试图找出它为什么阻碍程序运行;这就是支持使用源文件的一个有力论据。
切记有两条规则可以帮助您避免出现语法错误:
1. 确保命令位于括号中,而括号位于单引号中。没有使用这些字符之一必然导致程序无法运行。
2. 搜索命令需要位于斜线之间。要找出住在印第安那州的员工,您必须使用 “ /IN/ ” 而不是 “ IN ” 。
五、排序与排重
Sort 经常与 uniq 命令一起使用,从已排序的文件中删除完全相同的行。uniq 命令在管道中经常跟在 sort 命令的后面,还可以使用 -c 选项来计算某一行所出现的次数,或者使用 -d 选项,只报告完全相同的行:
$ sort -m test.out test2_sort.out | uniq -c 1 Another test. 1 Testing testing 2 This is a test.
在这里我们合并两个文件 test.out 和 test2_sort.out。然后我们使用 -c 选项,将输出传送到 uniq,这样最后的结果是按字母顺序排列的列表,完全相同的行被删除,并带有一个关于每行出现频率的报告。
# awk '/adq.jsp/{print$1}' log.txt |sort |uniq -c|sort -rn|more
列出access_log.txt 这个文件中第一个字段某一行所出现的次数。(-d参数作用 和数据库的distinct类似,但只显示重复的行。如果某个IP只有一行,它就不显示)
9 220.194.45.10
8 218.30.126.143
2 220.194.45.13
1 218.30.126.142
六、其它示例
1.将所有行的第一个字段,连接起来,并且用逗号分隔:
awk '{printf("%s,",$1)}' 2.txt >3.txt //把结果输出到了3.txt中