首页 > 代码库 > grep、sed、awk基础
grep、sed、awk基础
grep
grep :根据模式,搜索文本,并将符合模式的文本行显示出来,
使用基本正则表达式定义的模式来过滤文本的命令:
-i :忽略大小写
--color :加上颜色,
-v :显示没有被模式匹配到的行
-n:显示匹配到的行在文件中的行数
-w:精确匹配,只匹配整个单词,而不是字符串的一部分
-o :只显示被模式匹配到的字符串
-A #:after, 后#行
-B #: before, 前#行
-C #:context, 前后各#行
-c:显示一个文件被匹配到几行
-E :使用扩展正则表达式
-l:只列出匹配到的文件名
-L:列出不匹配的文件名,
grep -f file1 file2:显示file2中包含file1中的行
元字符:
. :匹配任意单个字符
[ ] :匹配指定范围内的任意单个字符
[^] :匹配指定范围外的任意单个字符
[ - ]:范围,如[A-Z],即A、B、C一直到Z都符合要求 。中括号里有的都会被匹配上[a-z0-9]
字符集合:
[:digit:]数字,
[:lower:] 小写字母,
[:upper:]大写字母,
[:punct:]标点符号,
[:space:]空白,
[:alpha:]所有字母,
[:alnum:]包含所有数字的字母
[[::digit]]$ :匹配以1个数字结尾的行
[[:space:]][[::digit]]$ :匹配以1个数字,前面为空白为结尾的行
which ls|grep -v ‘^alias‘|grep -o ‘[^[:space:]]*‘ #用grep去掉行首,-o:只显示被匹配到的
匹配次数:
* :匹配其前面字符任意次
.* :匹配任意长度的任意字符
\? :匹配其前面的字符1次或0次。前面需要加反斜线转义,ls |grep "pas\?"
\+ :匹配前面字符至少一次
\{m,n\}:匹配其前面的字符至少m次,至多n次。ls |grep "pas\{1,2\}"
\{m\}:匹配前面的字符m次;
\{0,n\}:匹配前面的字符至多n次;
\{1,\} :匹配其前面的字符至少1次,
位置锚定:
^ :锚定行首,此字符后面的任意内容必须出现在行首
$ :锚定行尾,此字符后面的任意内容必须出现在行尾
^PATTERN$: 用于模式匹配整行;
^$ :空行。注意:空格不等于空行
\<或\b :锚定词首,其后面的任意字符必须作为单词首部出现
\>或\b :锚定词尾,其前面的任意字符必须作为单词的尾部出现
\<root\> :表示精确匹配root这个单词,点号不算一个单词里面的字符
分组:
\(\):将一个或多个字符捆绑在一起,当作一个整体进行处理;
\(xy\)*ab
后向引用:引用前面的分组括号中的模式所匹配字符,(而非模式本身)
\1:从左侧起,第一个左括号以及与之匹配右括号之间的模式所匹配到的字符;
\(ab\+\(xy\)*\):
\1: ab\+\(xy\)*
\2: xy
grep ‘\(l..e\).*\1‘ test.txt ##前面出现l..e,后面调用这个单词,所以前后的一样;
He love his lover. 匹配出现相同字段的行
He like his liker.
egrep :扩展正则表达式,grep -E:
+ :匹配其前面的字符至少1次,不能为0次
{m,n}:也表示至少m次,至多n次,但是不要加反斜线了
():分组,也支持\1,\2,….,
a|b :或者,表示or的意思,C|cat表示匹配C或者cat,(C|c)at
IPV4:5类,A,B,C,D,E
A:1-127 B:128-191 C:192-223
2.grep命令使用简单实例
$ grep ‘test’ d* ##后可跟多个文件名,显示所有以d开头的文件中包含 test的行。
$ grep ‘[a-z]\{5\}’ aa
显示所有包含每个字符串至少有5个连续小写字符的字符串的行。
***默认情况下,’grep’只搜索当前目录。如果 此目录下有许多子目录,’grep’会以如下形式列出:
grep: sound: Is a directory
这可能会使’grep’ 的输出难于阅读。这里有两种解决的办法:
grep -r:明确要求搜索子目录
grep -d skip:或忽略子目录
$ grep magic /usr/src/Linux/Documentation/* | less 更方便阅读
***命令行参数
grep -C number pattern files :匹配的上下文分别显示[number]行,
grep pattern1 | pattern2 files :显示匹配 pattern1 或 pattern2 的行,
grep pattern1 files | grep pattern2 :显示既匹配 pattern1 又匹配 pattern2 的行。
***这里还有些用于搜索的特殊符号:
grep ‘$‘ /etc/init.d/nfs.server | wc -l 统计一个文件共有多少行
grep ‘\<[Tt]he\>‘ size.txt 匹配单词the,t或者T都可以
grep ‘[239].‘ data.doc #输出所有含有以2,3或9开头的,并且是两个数字的行
grep ‘^[^48]‘ data.doc #不匹配行首是48的行
grep -E ‘219|216‘ data.doc #使用扩展模式匹配
ps -ef|grep svn -c 查看svn这个进程的个数
grep -nf test1.txt test2.txt 匹配test1.txt中包含test2.txt内容的行,并显示行号
获取本机ip:
# ifconfig |sed -n ‘s#^.*addr:\(.*\) Bcast.*#\1#gp‘
# ifconfig |grep "inet addr"|awk -F "[: ]+" ‘{print $4}‘ +代表重复一次或多次分隔符
# ifconfig |grep "inet addr"|cut -d ":" -f2|cut -d " " -f1
# ifconfig |awk -F "[: ]+" ‘NR==2 {print $4}‘ #用:或空格作为分隔且可重复多次
# ifconfig |sed -n ‘/inet addr/p‘|sed ‘s#^.*addr:##g‘|sed ‘s#Bcast:.*$##g‘
sed:
-n :使用安静(silent)模式。只有经过sed 特殊处理的那一行(或者动作)才会被列出来。配合p
-e :替换时前面加-e,可替换多次,仅限于替换。用;也可实现
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r :支持扩展表达式,(默认是基础正规表示法语法)
-i :直接修改读取的文件内容,而不是输出到终端。
function:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何东东;
p :输出匹配到并改动的行。通常 p 会与参数 sed -n 一起运行~
q:退出。sed -n ‘1p;2p;5p;5q‘ files。 5q:处理到第5行退出,不往下匹配
s :替换
&:表示匹配到的内容。echo ‘12345‘|sed -r ‘s/./&\n/g‘ file #把数字竖着打印出来
增加或插入单行内容:
sed -i ‘2a *****‘ person.txt #在第二行增加*****内容,a是追加的意思,在之后追加
sed -i ‘2i *****‘ person.txt #在原第二行之前插入*****内容,$为末尾,插到倒数第二行
添加多行:
sed ‘2a ****\n****‘ person.txt #这样就可追加两行,\n换行,
sed ‘2a **** \ #结尾为\,下面会自动显示尖括号,再输入第二行 内容
>*****‘ person.txtt
sed正则表达式用法:
10{sed-commands} ##对第10行操作
10,20{sed-commands} ##对第10到20行操作,包括10,20行
10,+20{sed-commands} ##对第10到30(10+20)行操作,包括10,30行
1~2{sed-commands} ##对1,3,5,7,….行操作,等差数列
10,${sed-commands} ##对10到最后一行($代表最后一行)操作,包括第10行
/oldboy/{sed-commands} ##区间操作,对匹配oldboy的行操作
/oldboy/,/Alex/{sed-commands} ##对匹配oldboy的行到匹配Alex的行操作
/oldboy/,${sed-commands} ##对匹配oldboy的行到最后一行操作
1,/Alex/{sed-commands} ##对第一行到匹配Alex的行操作
d:删除指定的行,可用正则
sed ‘2d‘ person.txt ###指定删除第二行
sed ‘N;$d‘ file #删最后两行。删最后四行:cat file|sed ‘N;$d‘|sed ‘N;$d‘
cat 10|awk ‘NR==FNR{a++}NR!=FNR{if(FNR<=a-4)print $0}’ 10 10 #删除后四行
cat 10|head -n -4 #显示除了最后4行的全部行,-n:指定显示前多少行,
sed ‘2,5d‘ person.txt
sed ‘1d;3d‘ file #删除第一行和第三行
sed ‘3,$d‘ person.txt
sed ‘/=/!d‘ person.txt #!:取反,删除没被匹配到的,删除不包括=号的行
sed ‘1~2d‘ person.txt ###删除1,3,5,7…行
sed -r ‘/^$|[ \t]+/d‘ file #删除空行和一个或多个空格加制位符的行,
sed ‘/zhangyao/d‘ person.txt #匹配到zhangyao的行删掉,可用于打印不包含zhangyao的行
p:打印匹配行,-n:只显示匹配到行
sed ‘2p‘ person.txt ###打印两行
sed -n ‘2p‘ person.txt ###取消默认输出
sed -n ‘1,3p‘ person.txt ###打印出1-3行
sed -n ‘1~2p‘ person.txt ###打印出1,3,5,7…行
sed -n ‘$=‘ file #显示一个文件有几行
sed -n ‘1p;3p‘ file ##;是中断,只显示第一和第三行,而不是1-3行
sed -n ‘/==*/p‘ file #匹配一个或多个=的行,等同于 sed -nr ‘/=+/p‘ file
用新行取代旧行:
sed ‘2c *****‘ person.txt ###把第二行的内容替换成*****
文本替换:
sed -i ‘s#guopeng#xiaoying#g‘
sed -i ‘3s#guopeng#xiaoying#g‘ ###指定行进行替换
sed -i ‘98,115s/#//g‘ nginx.conf ##去掉注释
sed -i ‘98,117s/^/#/g‘ nginx.conf ##行首添加注释
sed -n ‘/bash/{s/bash/blueshell/;p;q}‘ /etc/passwd
如果只替换/etc/passwd的第一个bash关键字为blueshell,就退出
sed -e ‘3,$d‘ -e ‘s/bash/blueshell/‘ /etc/passwd #一条sed语句,执行多种操作
sed ‘s/^/HEAD&/g‘ test.file ## 在每行的头添加字符,比如"HEAD"
sed ‘s/$/&TAIL/g‘ test.file ##在每行的行尾添加字符,比如“TAIL”
sed引用外部变量:
sed "s/clone/$ip/g" file 等同于 sed ‘s/clone/‘$ip‘/g‘ #用双引或变量加双引
后向引用:
\U\1:把引用的\1内容变成大写,upper的缩写,\u:把首字母大写,\L小写
sed -r ‘s/(.*)([a-z]{3})(.*)/\3\U\2\1/g‘ file #把\2及之后的字母都变成大写
ifconfig eth0|sed -n ‘s/^.*inet addr:\(.*\) Bcast:.*$/\1/g‘ 过滤ip
ifconfig|sed -rn ‘s/^.*inet addr:(.*) Bcast:.*$/\1/g‘p ##不同版本sed需要加p
ifconfig eth0|sed -n ‘s/^.*inet addr:\(.*\) Bcast:\(.*\) Mask.*$/\1\t\2/g‘ 多引用
-r 扩展正则表达式,用-r就不用加反斜线,不用转义
# echo i am oldboy teacher.|sed ‘s#^.*am \([a-z].*\) tea.*$#\1#g‘
oldboy
# echo i am oldboy teacher.|sed -r ‘s#^.*am ([a-z].*) tea.*$#\1#g‘
oldboy
# chkconfig --list|grep "3:启用"|grep -vE "sshd|crond|network|rsyslog|sysstat"|awk "{print $1}"|sed -r ‘s#^(.*)#chkconfig \1 off#g‘|bash
高级编辑命令:
h: 把模式空间中的内容覆盖至保持空间中;
H:把模式空间中的内容追加至保持空间中;
g: 从保持空间取出数据覆盖至模式空间;
G:从保持空间取出内容追加至模式空间;
x: 把模式空间中的内容与保持空间中的内容进行互换;
n: 读取匹配到的行的下一行至模式空间;
N:追加匹配到的行的下一行至模式空间;
d: 删除模式空间中的行;
D:删除多行模式空间中的所有行;
sed -n ‘n;p‘ FILE:显示偶数行
sed ‘n;d‘ FILE: 显示奇数行;
sed ‘1!G;h;$!d‘ FILE:逆向显示文件内容
sed -n ‘1!G;h;$p‘ FILE: 逆向显示文件中的每一行;
sed ‘$!N;$!D‘ FILE: 取出文件后两行;
sed ‘$!d‘ FILE:取出文件最后一行;
sed ‘G‘ FILE:
sed ‘/^$/d;G‘ FILE: 把多个空白行合并成一个空白行
AWK:
http://lizhenliang.blog.51cto.com/7876557/1892112?b4
-F:指明输入时用到的字段分隔符
-v var=‘value‘ ##自定义变量
-F‘[: ]+‘ #以:号或空格一个或多个作为分隔符
-f:从文件中读取awk程序源文件,tail -n3 /etc/services |awk -f test.awk
1.print pring $1,$2,...
1.逗号分隔符,用双引号隔起来不做变量,
2.如省略item,相当于print $0:整行意思
3.‘print $1"\t"$2‘ #指定输出分隔,"":让输出字段用什么空格
2.变量:
內建变量:
FS:定义输入文件分隔符, 默认都为空白字符
awk ‘BEGIN{FS=""}{print $1,$2}‘ file #取消分隔符,现在每个字符作为一个字段
OFS:定义输出文件分隔符,默认都为空白字符
RS:指明输入时使用的换行符
ORS:指明输出时使用的换行符
NF:字段数,$NF:表示最后一个字段,$(NF-1)
echo "a b c d e f" |awk ‘{$NF="";$(NF-1)="";print$0}‘ 排除最后两个字段:
NR:行数
awk ‘NR>1&&NR<4{print NR,$0}‘ #取出第二至第三行,并显示行号
tail -n5 /etc/services |awk ‘NR==3{print $2}‘ 打印第三行第二个字段:
FNR:多文件分别统计行数,当FNR==NR时,说明在处理第一个文件内容,不等于时说明在处理
第二个文件内容。 一般FNR在处理多个文件时会用到
FILENAME:当前文件名
ARGC:命令行参数的个数
ARGV:数组,保存的是命令行所给定的各参数
awk -v FS=‘:‘ ‘{print $1}‘ /etc/passwd ##-v自定义变量FS,以:作为分隔符,再取第一段
awk -F: ‘{print $1}‘ /etc/passwd 也可以用-F然后接:,效果等同于自定义变量
awk -v FS=‘:‘ -v OFS=‘:‘ ‘{print $1,$3,$7}‘ /etc/passwd ##定义输出以什么作为分隔符,
awk ‘BEGIN{FS=":"}{print $1"#"$2}‘ /etc/passwd |head -n5 通过字符串拼接实现分隔:
awk ‘{print NF}‘ /etc/passwd 显示每行有多少个字段,不需要加$符,
awk ‘BEGIN{print ARGC}‘ /etc/fstab
awk ‘BEGIN{print ARGV[0|1|2|...]}‘ /etc/fstab
自定义变量和引用外部变量:
1.引用外部变量,需用‘BEGIN{print ‘$+变量名‘}‘ 括起来,如不行,"‘ ‘" 用这种,同sed
2.-v:自定义变量或引用外部变量
awk -v a=$a ‘{print a}‘ 或 awk ‘{print ‘$a‘} ‘ #$a为引用bash变量,
awk -v test=‘hello gawk‘ ‘BEGIN{print test}‘ 等同于
awk ‘BEGIN{test=‘hello gawk‘;print test}‘
3.printf
格式化输出:printf FORMAT,item1,item2,...
FORMAT:必须要给出
不会自动换行,需要显示给出换行控制符:\n
FORMAT中需要分别为后面每个item指定一个格式化符号
格式符:
%c:显示字符的ASCII码
%d,%i:显示十进制整数
%e,%E:科学计数法数值显示
%f:显示浮点数
%g,%G:以科学计数法胡浮点形式显示数值
%s:显示字符串
%u:无符号整数
%%:显示%自身
awk -F: ‘{printf "Username:%s,UID:%d\n",$1,$3}‘ /etc/passwd #$1赋值%s上,$3赋值在%d上
修饰符:
#[.#]:第一个数字控制显示的宽度,,第二个#表示小数点后的精度; %3.1f
-:左对齐。默认为右对齐
+:显示数值的符号
4.操作符:
算数操作符:x+y,x-y,x*y,x^y,x%y,-x,+x
字符串操作符:没有符号的操作符,字符串连接
赋值操作符:=,+=,-=,*=,/=,%=,^=,++,--
比较操作符:>,>=,<,<=,!=,==
模式匹配符:~(是否匹配),!~(是否不匹配)
awk ‘$2~/4567/{print $0}‘ #如果第二列匹配到4567,才执行后面的动作
awk ‘{if($2~/4567/){print $0}}‘ 等同于上
逻辑操作符:&& , || , !
seq 6 |awk ‘i=!i‘ 打印奇数行:
seq 6 |awk ‘!(i=!i)‘ 打印偶数行:
函数调用:function_name(argu1,argu2,...)
条件表达式:selector?if-true-expression:if-false-expression
在awk中,有3种情况表达式为假:数字是0,空字符串和未定义的值
awk ‘BEGIN{n=0;if(n)print"true";else print "false"}‘ 结果为:false
awk‘BEGIN{s="";if(s)print "true";else print"false"}‘ 结果为:false
awk‘BEGIN{if(s)print "true";else print "false"}‘ 结果为:false
seq 5 |awk ‘{print $0*2}‘ 乘法
seq 5 |awk ‘{print $0%2}‘ 取余
seq 5 |awk ‘$0%2==0{print $0}‘ 打印偶数行:
seq 5 |awk ‘$0%2!=0{print $0}‘ 打印奇数行
seq 5 |shuf |awk ‘{print$0|"sort"}‘ 管道符使用
例:
awk -F: ‘{$3>=1000?usertype="Common User":usertype="Sysadmin or SysUser";printf "%15s:%-s\n",$1,usertype}‘ /etc/passwd
:作为分隔符,第三列大于等于1000就命名为Common User,小于1000的命名为Sysadmin or SysUser,%15s对应$1,%s对应usertype,\n换行,-s左对齐,%15默认为右对齐
5.模式匹配
1.empty:空模式,匹配每一行
2./regular expression/:仅处理能够被此处的模式匹配到的行
awk ‘/^UUID/{print $1}‘ /etc/fstab centos 7的fstab文件以UUID开头。
awk ‘!/^UUID/{print $1}‘ /etc/fstab 取反
tail /etc/services |awk ‘/^blp5/{print $0}‘ 匹配开头是blp5的行:
tail /etc/services |awk ‘/^[a-z0-9]{8} /{print $0}‘ 匹配第一个字段是8个字符的行:
不匹配开头是#和空行:
awk‘! /^#/ && ! /^$/{print $0}‘ /etc/httpd/conf/httpd.conf
awk‘! /^#|^$/‘ /etc/httpd/conf/httpd.conf
awk‘/^[^#]|"^$"/‘ /etc/httpd/conf/httpd.conf
3.relational expression:关系表达式: 结果有“真”有“假”:结果为"真"才会被处理
真:结果为非0值,非空字符串;
awk -F: ‘$3>=1000{print $1,$3}‘ /etc/passwd
awk -F: ‘$NF=="/bin/bash"{print $1,$NF}‘ /etc/passwd
awk -F: ‘$NF"~/bash$/"{print $1,$NF}‘ /etc/passwd
以bash$为结尾的模式匹配,模式匹配要用//括起来
4.匹配行范围:/path1/,/path2/
awk -F: ‘/^root/,/^nobody/{print $1}‘ /etc/passwd
匹配root起始的行到nobody开头的行中间的行,取第一个字段值
awk -F: ‘(NR>=2&&NR<=10){print $1}‘ /etc/passwd
5.BEGIN/END模式:
BEGIN{}:还没匹配第一行之前,先执行BEGIN的行为,用于变量赋值,输出标头
END{}:在文本处理完成之后执行END的语句,用于变量最终的输出,取最后一行
cat 10.txt|awk ‘{a+=$1}END{print a}‘ #输出1加到10的值,竖列
pa aux|awk ‘/\java/{a+=$3;b+=$4}END{print "cpu:"a" mem:"b}‘ #统计进程cpu和内存
awk -F: ‘BEGIN{print " username uid \n---------------------"}{print $1,$3}END{print "==========\n end"}‘ /etc/passwd
6.控制语句:
6.1:if-esle
语法:‘{if(condition) {statments} else {statments}}‘ 双分支if语句
‘/^_/{if(***)print $0}‘ #if前面还可以接正则匹配过滤,在判断
seq 5 |awk ‘{if($0==3)print $0;else print "no"}‘
awk‘{if($1==4){print "1"} else if($2==5){print "2"} elseif($3==6){print "3"} else {print "no"}}‘ file
awk -F: ‘{if($3>=1000) print $1,$3}‘ /etc/passwd
awk -F: ‘{if($NF=="/bin/bash") print $1}‘ /etc/passwd
awk -F: ‘{if($3>=1000) {printf "Common user:%s\n",$1} else {printf "root or SysUser:%s\n",$1}}‘ /etc/passwd centos 7是1000,centos 6是500
awk ‘{if(NF>5) print $0}‘ /etc/fstab 使用场景:对awk取得的整行或某个字段做条件判断
df -h|awk -F[%] ‘/^\/dev/{print $1}‘|awk ‘{if($NF>=20)print $1}‘ 挑出dev使用率大于20的磁盘
6.2:while循环
语法:while(condition) statments
条件为“真”,进入循环,条件为“假”,退出循环
使用场景:对一行内的多个字段逐一类似处理时使用;对数组中的各元素逐一处理时使用
length() 计算长度函数
awk ‘/^[[:space:]]*linux16‘/{i=1;while(i<=NF) {print $i,length($i);i++}}‘ /etc/grub2.cfg
对每一行的每一个字段做单独的统计
awk ‘/^[[:space:]]*linux16/{i=1;while(i<=NF) {if(length($i)>=7) {print $i,length($i)};i++}}‘ /etc/grub2.cfg while循环里面再嵌套if语句
break跳过所有循环,continue跳过当前循环。
awk ‘BEGIN{for(i=1;i<=5;i++){if(i==3){break};print i}}‘
awk ‘BEGIN{for(i=1;i<=5;i++){if(i==3){continue};print i}}‘
exit退出程序,与shell的exit一样。[ expr]是0-255之间的数字。
seq5 |awk ‘{if($0~/3/)exit (123)}‘
echo $?
123
6.3:do-while循环:至少执行一次循环体
6.4:for循环
语法:for (variable assignment;condition;iteration process) {for-body}
awk ‘/^[[:space:]]*linux16/{for (i=1;i<=NF;i++) {print $i,length($i)}}‘ /etc/grub2.cfg
awk ‘{for(i=1;i<=NF;i++){n++}}END{print n}‘ file #统计文件有多少个单词,可用wc
n++:每循环一次就加1
awk ‘{for(i=1;i<=NF;i++){if($i=="60"){n++}}}END{print n}‘ file1 #统计有多少个60
df -h|awk -F‘[\t %]+‘ ‘{a=a+$5}END{print a}‘ #统计磁盘总使用率,竖列相加
特殊用法:能够遍历数组中的元素:
语法:for(var in array) {for-body}
6.5:switch语句:
switch(expression) {case VALUE1 or /REGEXP/: statement;case VALUE2 or /REGEXP2/: statement;...;default:statement;}
6.6 next:在行间执行,提前结束
awk -F: ‘{if($3%2!=0) next; print $1,$3}‘ /etc/passwd
如果$3项除2不等于0,就直接跳到下一行处理。
7.array:数组
关联数组:array[index-expression]
index-expression:
1.可使用任意字符串,字符串要使用双引号
2.如果某数组元素事先不存在,在引用时,awk会自动创建此元素,并将其值初始化为"空串"
若要判断数组中是否存在某元素,要使用"index in array"格式进行
awk ‘BEGIN{weekdays["mon"]="monday";weekdays["tue"]="tuesday";print weekdays["mon"]}‘
若要遍历数组中的每个元素,要使用for循环。
注意:var会遍历array的每个索引
state["LISTEN"]++ 此处LISTEN为下标
state["ESTABLISHED"]++
awk ‘BEGIN{weekdays["mon"]="monday";weekdays["tue"]="tuesday";for(i in weekdays) print weekdays[i]}‘
netstat -tan|awk ‘/^tcp\>/{state[$NF]++}END{for(i in state) {print i,state[i]}}‘
awk ‘{ip[$1]++}END{for(i in ip) {print i,ip[i]}}‘ /var/log/httpd/access_log ##计算访问ip数量
awk ‘{for(i=1;i<=NF;i++){count[$i]++}}END{for(i in count) {print i,count[i]}}‘ /etc/fstab
##统计文件中每个文件出现的次数
去重三个方法:
awk ‘++a[$1]==1‘ file #同下面一行都是以最开始匹配到为基准,后面重复的忽略
awk ‘!a[$1]++‘ file #省略{print $0},对第4列去重就是$4
awk ‘{a[$1]=$0}END{for (i in a){print a[i]}}‘ #以最终的为基准,不断赋值,
计数:
awk ‘{a[$1]+=1}END{for(i in a){print i,a[i]}}‘ file
例1:
cat file
a 1
a 2
b 3
b 4
cat file|awk ‘{a[$1]=a[$1]+$2}END{for(i in a){print i,a[i]}}‘ #计算多个a和多个b各自的值
a 3
b 7
处理多文件:
awk ‘NR==FNR{a[FNR]=$1}NR!=FNR{print a[FNR],$2}‘ file file1
把一个文件的第一列和另一个文件的第二列拼凑起来
NR==FNR:表示处理第一个文件。
NR!=FNR:表示处理第二个文件
处理多文件计数:
awk ‘{a[$1]=a[$1]+$2}END{for(i in a){print i,a[i]}}‘ file file1 file2
二维数组行列转换:
awk ‘{for(i=1;i<=NF;i++){a[NR,i]=$i}}END{for(i=1;i<=NF;i++){for(j=1;j<=NR;j++){printf a[j,i]" "}print ""}}‘
修改第一列值:
cat file|awk ‘{$1=3}1‘ === cat file |awk ‘{$1=3;print $0}‘
两个文件行中有相同字段,合并并且以file1为准,file1需放后面:
awk ‘NR==FNR{a[$1]=$0;next}NR!=FNR{$1=a[$1];print $0}‘ file2 file1
grep、sed、awk基础