sed
sed 编辑器逐行处理文件,并将输出结果发送到屏幕,不会修改或破坏源文件
-i会直接修改文件
语法
代码语言:javascript复制sed [-hnV][-e<script>][-f<script文件>][文本文件]
参数说明:
代码语言:javascript复制-e<script>或--expression=<script> 以选项中指定的script来处理输入的文本文件。
-f<script文件>或--file=<script文件> 以选项中指定的script文件来处理输入的文本文件。
-n 仅显示script处理后的结果。不打印模式空间中的内容,而是仅打印和sed命令匹配的内容
-i 直接对源文件进行修改(慎用)
动作说明:
代码语言:javascript复制a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何东东;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :打印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是 /正则/
测试文件
代码语言:javascript复制[root@VM---centos ~]# cat testfile
xujinding
wuyicheng
caiyufei
wahaha
hello world
hello java
删除
将 testfile 的内容列出并且列印行号,同时,请将第 2~4 行删除
代码语言:javascript复制nl testfile | sed '2,4d'
1 xujinding
5 hello world
6 hello java
只删除第二行
代码语言:javascript复制nl testfile | sed '2d'
删除第3行~到最后一行 $代表最后
代码语言:javascript复制nl testfile | sed '3,$d'
插入
在第二行后(即加在第三行) 加上drink tea
代码语言:javascript复制nl testfile | sed '2a drink tea'
1 xujinding
2 wuyicheng
drink tea
3 caiyufei
4 wahaha
5 hello world
6 hello java
代码语言:javascript复制在第二行前(即加在第二行) 加上drink tea
nl testfile | sed '2i drink tea'
第二行后面加入两行字 使用可以一次加多行,每一行之间都必须要以反斜杠 来进行新行标记
代码语言:javascript复制nl testfile |sed '2a drink tea or
> drink beer'
1 xujinding
2 wuyicheng
drink tea or
drink beer
3 caiyufei
4 wahaha
5 hello world
6 hello java
以行为单位的替换与显示
将第二行到第五行换成 xixixixixi
代码语言:javascript复制nl testfile |sed '2,5c xixixixixi'
1 xujinding
xixixixixi
6 hello java
打印
n和p 一般是一起使用
代码语言:javascript复制-n选项:只显示匹配处理的行(否则会输出所有)(也就是关闭默认的输出)
-p选项:打印
[root@centos6 ~]# vim a.txt
[root@centos6 ~]# cat a.txt
asdf;1324;fdsag
1234567890
qwer
asdasdsadasdasdas
[root@centos6 ~]# sed 's/1324/aaaa/' a.txt > b.txt 首先sed是有一个默认输出的,也就是将所有文件内容都输出,加上命令行中的替换,那么输出结果就是下面这样
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
1234567890
qwer
asdasdsadasdasdas
[root@centos6 ~]# sed 's/1324/aaaa/p' a.txt > b.txt 这行的意思就是:首先sed默认输出文件全部内容,然后p又将匹配到的内容打印了一遍,也就是会输出两边匹配到的内容
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
asdf;aaaa;fdsag
1234567890
qwer
asdasdsadasdasdas
[root@centos6 ~]# sed -n 's/1324/aaaa/p' a.txt > b.txt 这行就是sed -n屏蔽默认输出然后s替换,p再将匹配到的内容打印出来,所以只显示了一行,也就是匹配到的那一行
[root@centos6 ~]# cat b.txt
asdf;aaaa;fdsag
[root@centos6 ~]# sed -n 's/1324/aaaa/' a.txt > b.txt 这行就是sed -n选项屏蔽默认输出,s替换,但是没有p就不会将匹配到的内容输出
[root@centos6 ~]# cat b.txt
[root@centos6 ~]#
代码语言:javascript复制仅列出 testfile 文件内的第 5-7 行
nl testfile | sed -n '5,7p'
数据的搜寻并显示
搜索 testfile 有 hello 关键字的行:
代码语言:javascript复制nl testfile | sed -n '/hello/p'
5 hello world
6 hello java
数据的搜寻并删除
删除 testfile 所有包含 hello 的行,其他行输出
代码语言:javascript复制nl testfile | sed '/hello/d'
1 xujinding
2 wuyicheng
3 caiyufei
4 wahaha
数据的查找与替换
sed ‘s/要被取代的字串/新的字串/g’ g 标识符表示全局查找替换
将 testfile 文件中每行第一次出现的 hello 用字符串 heihei 替换,然后将该文件内容输出到标准输出:
代码语言:javascript复制nl testfile | sed 's/hello/heihei/'
1 xujinding
2 wuyicheng
3 caiyufei
4 wahaha
5 heihei world
6 heihei java
注意 是每行第一个 (第5行的第2个o没被替换掉)
代码语言:javascript复制nl testfile | sed 's/o/heihei/'
1 xujinding
2 wuyicheng
3 caiyufei
4 wahaha
5 hellheihei world
6 hellheihei java
sed 对文件中所有符合的字符串都被替换,修改后内容会到标准输出,不会修改原文件:
代码语言:javascript复制sed -e 's/oo/kk/g' testfile
修改源文件(-i)
代码语言:javascript复制sed -i 's/oo/kk/g' testfile
多点编辑(-e)
一条 sed 命令,删除 testfile 第三行到末尾的数据
代码语言:javascript复制nl testfile | sed -e '3,$d' -e 's/HELLO/RUNOOB/'
cut
cut 的工作就是“剪”,具体的说就是在文件中负责剪切数据用的。cut 命令从文件的每一行剪切字节、字符和字段并将这些字节、字符和字段输出。
语法
代码语言:javascript复制cut [选项参数] filename
说明:默认分隔符是制表符 参数说明
代码语言:javascript复制-f: 列号,提取第几列
-d: 分隔符,按照指定分隔符分割列
-c: 指定具体的字符
测试文件
[admin@ datas]$ vim words hello world !! hadoop spark hive 张三 李四 王五
简单实例
根据空格切割 words 第一、三列
代码语言:javascript复制cut -d " " -f 1,3 words
根据空格切割,获取 words 第 2 行第 1 列
代码语言:javascript复制cat words | head -n 2 | tail -n 1 | cut -d " " -f 1
选取系统 PATH 变量值
代码语言:javascript复制[admin@ datas]$ echo $PATH
选取系统 PATH 变量值,第 2 个“:”开始后的所有路径:
[admin@ datas]$ echo $PATH | cut -d : -f 2-
选取系统 PATH 变量值,第 4 列(包括第 4 列)之前的所有路径:
[admin@ datas]$ echo $PATH | cut -d : -f -4
选取系统 PATH 变量值,第 2 到 4 列(包括第 2 到 4 列)之间的所有路径:
[admin@mc datas]$ echo $PATH | cut -d : -f 2-4
切割 ifconfig 后打印的 IP 地址
代码语言:javascript复制[admin@ ~]$ ifconfig
获取 ip 地址
[admin@ ~]$ ifconfig | grep "inet" | tail -n 1 | cut -d " " -f 9- | cut -d " " -f 2
awk
一个强大的文本分析工具,把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再进行分析处理。
语法
代码语言:javascript复制awk [选项参数] ‘pattern1{action1} pattern2{action2}...’ filename
pattern:表示 AWK 在数据中查找的内容,就是匹配模式 action:在找到匹配内容时所执行的一系列命令
选项参数 -F: 指定输入文件折分隔符 -v(小写): 赋值一个用户定义变量(action1里面是不能引用awk外面的变量)
自定义变量(-v)
代码语言:javascript复制awk -v x="bob" -v y=10 '{print x,y}' /tmp/hosts
自定义分隔符(-F)
代码语言:javascript复制awk -F ':' {print $1}' words
awk -F: {print $1}' words
二维数组
代码语言:javascript复制echo " "|awk 'BEGIN{ay[1,10]=5;ay[10,2]=12;}END{for (k in ay) {split(k,idx,SUBSEP);print idx[1],idx[2],ay[idx[1],idx[2]];}}'
输出结果:
1 10 5
10 2 12
echo " "|awk 'BEGIN{ay[1,10]=5;ay[10,2]=12;}END{for (k in ay) {print k,ay[k];}}'
输出结果:
110 5
102 12
多个分隔符
代码语言:javascript复制[root@VM---centos ~]# vim awktest
xu jin:ding
wu yi:cheng
cai yu:fei
awk -F '[ ,:]' '{print $1,$2,$3}' awktest
按空格和分号拆分
xu jin ding
wu yi cheng
cai yu fei
内置变量RS、OFS、ORS
RS
内置变量RS保存的是输入数据的行分隔符,默认为n,可以指定其它字符作为行分隔符
代码语言:javascript复制
awk -v RS="." '{print $1}' /tmp/hosts #指定.作为行分隔符
OFS
保存的是输出字段的分隔符(列分隔符),默认为空格
代码语言:javascript复制
awk -v OFS="-" '{print $1,$2}' /tmp/hosts #以"-"作为字段分隔符
ORS
保存的是输出记录(行)的分隔符
代码语言:javascript复制
awk -v ORS="-" '{print $1}' /tmp/hosts
可以输出常量和变量,如果是字符串常量需要用双引号括起来,数字常量可以直接打印
代码语言:javascript复制awk '{print 123}' /tmp/hosts
awk '{print "IP:",$1}' /tmp/hosts
awk '{print "第1列:"$1,"t第2列:"$2}' /tmp/hosts
正则
代码语言:javascript复制awk 可以使用正则
搜索 passwd 文件,以:分隔,输出以 a 字母开头的所有行
[admin@ datas]$ awk -F ':' '/^a/{print $0}' passwd
搜索 passwd 文件,以:分隔,输出以 a 字母开头的所有行的第 1 列和第 6 列,两列之间加上--字符
[admin@ datas]$ awk -F ':' '/^a/{print $1"--"$6}' passwd
注意:有正则的时候,只有匹配了 pattern 的行才会执行 action
搜索 passwd 文件,输出以 a 字母开头的所有行的第 1 列和第 6 列,以--分割,且在开头第一行的上面添加一行列名“1 列”“6 列”,以--分隔,在最后一行的下面添加一行内容"这是所有的以 a 开头的行的 1、6 两列"。
[admin@ datas]$ awk -F ':' 'BEGIN{print "1 列--6 列"} /^a/{print $1"--"$6} END {print "这是所有的以 a 开头的行的 1、6 两列"}' passwd
显示xu第一次出现到ding第一次出现之间的行(包含xu和ding对应的行)
awk '/xu/,/ding/ {print $1}' awktest
BEGIN和END
BEGIN可以进行数据初始化,END可以进行数据汇总 BEGIN:读取所有数据之前执行一次(只会执行一次) END:读取完所有数据记录后执行一次(只会执行一次)
IF
代码语言:javascript复制ps -eo user,pid,pcpu,comm | awk '{if($3>0.5) print}'
awk -F: '{if($3<1000){x } else{y }} END{print "系统用户个数:"x"","普通用户个数:"y""}' /etc/passwd
遍历数组
代码语言:javascript复制awk 'BEGIN{
> a[0]=1;a[11]=22;a["book"]=32;a["work"]="home";
> for(i in a){print i,a[i]}
> }'
因为awk中数组的下标可以是数字和字母,数组的下标通常被称为关键字(key)。值和关键字都存储在内部的一张针对key/value应用hash的表格里。由于hash不是顺序存储,因此在显示数组内容时会发现,它们并不是按照你预料的顺序显示出来的
for循环
代码语言:javascript复制for(表达式;表达式;表达式) {
动作指令序列
}
awk 'BEGIN{ for (i=1;i<=4;i ) {print i}}'
awk -F: '{
for(i=1;i<=NF;i )
> {if($i=="root") x }
> } END {print x}' /etc/passwd
while循环
代码语言:javascript复制while(条件判断){
动作指令序列;
}
awk 'BEGIN{ i=1; while(i<=5) {print i;i }}'
常用命令
打印各磁盘可用大小
代码语言:javascript复制df | grep -v tmpfs | awk 'NR!=1 {disk[$1]=$4}
END {for(i in disk) {printf "%-20s %-10sn",i,disk[i]/1024"M"}
}'
统计磁盘可用容量
代码语言:javascript复制df | tail -n | grep -v tmpfs | awk '{sum =$4} END{print "磁盘可用容量:"sum/1024/1024"G"}'
统计/etc下文件总大小
代码语言:javascript复制ls -l /etc | awk '/^-/{sum =$5} END{print "文件总大小:"sum/1024"M"}'
统计访问Nginx的各IP访问次数
代码语言:javascript复制awk '
{IP[$1] }
END {
for (i in IP) {print i,IP[i]}
}' /var/log/nginx/access.log
查看Nginx 1点到5点半的日志
代码语言:javascript复制awk -F"[: /]" '$7":"$8 >= "01:00" && $7":"$8 <="05:30"' /var/log/nginx/access.log
根据学号汇总查询每个学生的总成绩
代码语言:javascript复制[admin@ datas]$ vim grade.txt
#学号 科目 成绩
1 语文 90
1 数学 40
1 英语 59
2 语文 95
2 数学 80
2 英语 52
3 语文 89
4 数学 29
(1)使用 awk 命令行,根据学号汇总查询每个学生的总成绩
[admin@ datas]$ cat grade.txt | grep -v "#" | awk '{arr[$1] =$3} END{for(i in arr){printf("学号为%d 的学生的成绩是:%dn",i,arr[i])}}'
统计每个接口的访问次数及平均时间
代码语言:javascript复制//查询接口的访问次数
less -r xxx | awk -F '|' '{API[$4] } END{ for(i in API) {print i,API[i]}}'
//查询接口的访问次数并排序
cat product-service-action.2022-06-02_16.log | awk -F '|' '{API[$4] } END{ for(i in API) {print i,API[i] | "sort -r -n -k2"}}'
//查接口的访问次数。并统计每个接口的总时间
cat product-service-action.2022-06-02_16.log | awk -F '|' '{API[$4] ;TIME[$4]=int(TIME[$4]) int($5)} END{ for(i in API) {print i,API[i],TIME[i]}}'
//查接口的访问次数。并统计每个接口的平均响应时间
cat product-service-action.2022-06-02_16.log | awk -F '|' '{API[$4] ;TIME[$4]=int(TIME[$4]) int($5)} END{ for(i in API) {print i,API[i],TIME[i],int(TIME[i] / API[i]) | "sort -r -n -k4" }}'
//查2s以上接口的访问次数。并统计每个接口的平均响应时间
cat product-service-action.2022-06-02_16.log | awk -F '|' '{if(int($5)>2000){ API[$4] ;TIME[$4]=int(TIME[$4]) int($5)}} END{ for(i in API) {print i,int(TIME[i] / API[i])}}'
我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=23endckh44e8w