linux三剑客

linux三剑客

grep作用

在文件或标准输入中,通过正则表达式查找对应的内容

语法格式

 

grep [选项]... PATTERN [FILE]...

grep的常用选项参数

参数选项描述
-G默认值
-F相当于使用fgrep,但必须用 -F
-E相当于使用egrep,但必须用 -E
-V打印 grep 的版本号

-E 的栗子

前提 :当 grep 想同时过滤多个条件或操作

错误写法:

默认不支持多条件匹配

ps -ef | grep "java|tomcat"

正确写法:

ps -ef | grep -E "java|tomcat"

匹配控制选项参数

参数选项描述
-ePATTERN 来进行匹配操作
-f从文件中取得 PATTERN
-i忽略大小写
-v反转匹配,选择没有被匹配到的内容
-w匹配整词,精确地单词,单词的两边必须是非字符符号(即不能是字母数字或下划线)
-x仅选择与整行完全匹配的匹配项
--line-buffered有一个文件是动态的,它不断地添加信息到文件的尾部,而你想要输出包含某些信息的行。即持续的grep一个动态的流

-e 的栗子

当你有多个正则表达式想同时匹配时,可以用 -e,一个 -e 接一个正则表达式,它们是或的关系,不是与的关系.

-f 的栗子

-i 的栗子

-v 的栗子

-w 的栗子

-x 的栗子

一般输出控制选项

参数选项描述
-s禁止显示错误信息
-q安静模式,不会有任何输出内容,查找到匹配内容会返回0,未查找到匹配内容就返回非0
-m num匹配 num 次后停止
-c匹配成功数量
-l列出匹配成功结果的文件来源(标准输入或文件名称)
-H给每一个匹配结果打印来源(标准输入、文件名)
-q 的栗子

目前未发现任何作用

-m 的栗子

-c 的栗子

-l 的栗子

ls 输出的内容就是标准输入

输出控制参数讲解

参数选项描述
-b输出的同时打印字节偏移
-n输出的同时打印行号
-H给每一个匹配结果打印来源(标准输入、文件名)
-h输出是不显示来源(默认)
-o只显示匹配 PATTERN 的部分

-b 的栗子

-n 的栗子

-H 的栗子

因为结果都来源于 ls 的标准输入,所以显示标准输入,如果是来源于某个文件则会显示文件名

-o 的栗子

文件和目录选项

参数选项描述
-a不忽略二进制的数据
-d当要查找的是目录而非文件时,必须使用这项参数
-r以递归方式读取每个目录下的所有文件; 这相当于-d recurse选项。

巨常用的语法:

重点

写的正则表达式最好用 ' ' 包起来,当碰到需要转义符的时候才会生效

查找指定进程

ps -ef | grep java

查找指定进程并统计数量

ps -ef | grep -c java

从文件中查找关键字

 

grep src test.txt

从文件中查找关键字并输出它的行号
 

grep -n src test.txt

从多个文件中查找关键字

 

grep src src.txt src1.txt src2.txt

从文件中查找关键字后,再从结果中找到指定关键字

 

cat src.txt | grep -v s | grep -w lib

找出文件中的空白行

 

grep -n ^$ test.txt

显示当前目录下面以 .txt 结尾的文件中的所有包含每个字符串至少有4个连续小写字符的字符串的行

 

grep -n "[a-z]\{4\}" *.txt

sed作用

sed是一个流编辑器,非交互式的编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“缓冲空间”(pattern space) 。接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。

文件内容并没有改变,除非使用重定向存储输出。

sed用来自动编辑一个或多个文件,简化对文件的反复操作,编写转换程序等

sed语法

sed [选项] [sed指令] [输入文件]

选项参数:

p==显示在模式空间的内容

d:删除

=: 打印匹配行的行号

-n: 取消默认的完整输出,只要需要的

-e: 允许多项编辑

-i: 修改文件内容

-r: 支持拓展正则表达式(|、() )

s///:查找替换,其分隔符可自行制定,常见的有s@@@,s###

命令参数:

a:在当前行后添加一行或多行

c:在当前行进行替换修改

d:在当前行进行删除操作

i:在当前行之前插入文本

p:打印匹配的行或指定行

n:读入下一输入行,从下一条命令进行处理

!:对所选行以外的所有行应用命令

h:把模式空间里的内容重定向到暂存缓冲区

H:把模式空间里的内容追加到暂存缓冲区

g:取出暂存缓冲区的内容,将其复制到模式空间,覆盖该处原有内容

G:取出暂存缓冲区的内容,将其复制到模式空间,追加该处原有内容

sed常用命令

创建测试文件

[root@yfy ~]# cat>person.txt<<EOF

> 101,zhangsan,CEO

> 102,lisi,CTO

> 103,Alex,COO

> 104,wangwu,CFO

> 105,zhaoliu,CIO

> EOF

(1)查询

只打印第一行

 

[root@yfy ~]# sed -n '1p' person.txt

101,zhangsan,CEO

查看第3到4行

 

[root@yfy ~]# sed -n '3,4p' person.txt

104,wangwu,CFO

105,zhaoliu,CIO

包含Alex的行

 

[root@yfy ~]# sed -n '/Alex/p' person.txt

103,Alex,COO

最后一行

 

[root@yfy ~]# sed -n '$p' person.txt

105,zhaoliu,CIO

已w开头,u结尾的行

 

[root@yfy ~]# sed -n '/w.*u/p' person.txt

104,wangwu,CFO

从包含101的行到包含104的行

 

[root@yfy ~]# sed -n '/101/,/104/p' person.txt

101,zhangsan,CEO

102,lisi,CTO

103,Alex,COO

104,wangwu,CFO

查询有wangwu或者lisi的行

如果只用-n是查不出来的,因为默认情况下,sed只支持基本正则表达式。

 

[root@yfy ~]# sed -rn '/lisi|wangwu/p' person.txt

102,lisi,CTO

104,wangwu,CFO

查询指定分行

 

[root@yfy ~]# sed -n '2p;4p' person.txt

102,lisi,CTO

104,wangwu,CFO

将符合制定内容的文本存入另一个文本中

 

[root@yfy ~]# sed -n '/^104/w hello.txt' person.txt

[root@yfy ~]# cat hello.txt

104,wangwu,CFO

通过正则取出绝对路径

 

[root@yfy ~]# echo "/var/log/messages" |sed 's#/.*/##'

messages

(2)新增

a ====== append 追加

i ====== insert 插入

在第二行后面加一个新行

 

[root@yfy ~]# sed '2a hello world' person.txt

101,zhangsan,CEO

102,lisi,CTO

hello world

103,Alex,COO

104,wangwu,CFO

105,zhaoliu,CIO

在第二行插入一行

 

[root@yfy ~]# sed '2i hello world' person.txt

101,zhangsan,CEO

hello world

102,lisi,CTO

103,Alex,COO

104,wangwu,CFO

105,zhaoliu,CIO

(3)删除

删除第一行

 

[root@yfy ~]# sed '1d' person.txt

102,lisi,CTO

103,Alex,COO

104,wangwu,CFO

105,zhaoliu,CIO

显示文件内容但是不包含Alex

方法一:

 

[root@yfy ~]# grep -v "Alex" person.txt

101,zhangsan,CEO

102,lisi,CTO

104,wangwu,CFO

105,zhaoliu,CIO

方法二:

 

[root@yfy ~]# sed '/Alex/d' person.txt

101,zhangsan,CEO

102,lisi,CTO

104,wangwu,CFO

105,zhaoliu,CIO

方法三:(没生效,应该写的不对,后期改正。。。)

 

[root@yfy ~]# awk '!/Alex/d' person.txt

101,zhangsan,CEO

102,lisi,CTO

103,Alex,COO

104,wangwu,CFO

105,zhaoliu,CIO

方法四:

 

[root@yfy ~]# sed -n '3!p' person.txt

101,zhangsan,CEO

102,lisi,CTO

104,wangwu,CFO

105,zhaoliu,CIO

删除配置文件中#开头的注释行

 

sed '/^#/d' my.conf

(4)修改

指定某行进行内容替换

 

[root@yfy ~]# sed -i '7c SELINUX=Disabled' /etc/selinux/config

正则匹配对应内容,然后进行替换

 

[root@yfy ~]# sed -i '/^SELINUX=/c SELINUX=Disabled' /etc/selinux/config

(5)替换

's/old/new/g'

's#old#new#g'

's@old@new@g'

s#old#new#:只会替换每一行的第一个内容

将所有数字替换成*

 

[root@yfy ~]# sed 's#[0-9]#*#g' person.txt

***,zhangsan,CEO

***,lisi,CTO

***,Alex,COO

***,wangwu,CFO

***,zhaoliu,CIO

3.练习

反向引用获取id

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 每行第一个字段

NF 字段数量变量

NR 每行的记录号,多文件记录递增

FNR 与NR类似,不过多文件记录不递增,每个文件都从1开始

\t 制表符

\n 换行符

FS BEGIN时定义分隔符

RS 输入的记录分隔符, 默认为换行符(即文本是按一行一行输入)

~ 匹配,与==相比不是精确比较

!~ 不匹配,不精确比较

== 等于,必须全部相等,精确比较

!= 不等于,精确比较

&& 逻辑与

|| 逻辑或

+ 匹配时表示1个或1个以上

/[0-9][0-9]+/ 两个或两个以上数字

/[0-9][0-9]*/ 一个或一个以上数字

FILENAME 文件名

OFS 输出字段分隔符, 默认也是空格,可以改为制表符等

ORS 输出的记录分隔符,默认为换行符,即处理结果也是一行一行输出到屏幕

-F'[:#/]' 定义三个分隔符

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

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

awk -F: '{if($3<100) next; else print}' /etc/passwd //小于100跳过,否则显示

awk -F: 'BEGIN{i=1} {if(i<NF) print NR,NF,i++ }' /etc/passwd

awk -F: 'BEGIN{i=1} {if(i<NF) {print NR,NF} i++ }' /etc/passwd

另一种形式

awk -F: '{print ($3>100 ? "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

awk数组(重要)

awk的数组,一种关联数组(Associative Arrays),下标可以是数字和字符串。因无需对数组名和元素提前声明,也无需指定元素个数 ,所以awk的数组使用非常灵活。

首先介绍下几个awk数组相关的知识点:

<1>建立数组

 

array[index] = value :数组名array,下标index以及相应的值value

<2>读取数组值

 

{ for (item in array) print array[item]} # 输出的顺序是随机的

{for(i=1;i<=len;i++) print array[i]} # Len 是数组的长度

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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值