sed 以及 awk用法

时间:2023-12-04 19:39:50

  

sed 格式
sed[options] "script" FILE....

选项:
-n:静默模式,不输出模式空间内的内容;默认打印空间模式的内容
-r:扩展的正则表达式
-f 文件:指定sed脚本文件
-e 'script' -e 'script' :指定多个编辑指令
-i : 直接编辑原文件

编辑命令:
d:删除
p: 打印
i \text:在被指定到的行前面插入文本
a \text:在被指定的行的下面插入文本
\n:换行
r /path/file.txt:在指定位置把另外一个文件的内容插入
w /path/file.txt:将符合条件的所有行保存至指定文件中
=:显示符号条件的行的行号
s///:查找条件可以使用模式,但是要替换的内容不行

sed '地址定界s@查找条件@替换文件@'
修饰符:
g:global,全局替换
i:ignore-case,不区分字符大小写

地址定界:自定义的起始行到结束行
startline,endline
1,3
/pat1/,/pat2/
/pattern/

用法:sed [options] 'addr1[,addr2]编辑命令' FILE...
sed [options] "addr1[,addr2]编辑命令" FILE...

用法

. 删除 /etc/puppet/puppet.conf 1到13行的数据
[root@k8s1 ~]# sed '1,13d' /etc/puppet/puppet.conf 2. 删除以空格或者tab的集合开头的行
[root@k8s1 ~]# sed '/^[[:space:]]/d' /etc/puppet/puppet.conf  3.删除空行
[root@k8s1 ~]# sed '/^[[:space:]]*$/d' /etc/puppet/puppet.conf 4.删除fstab中以/ 开头的行。
[root@k8s1 ~]# sed '/^\//d' /etc/fstab 5.删除第2行到第一次出现 / 的行,结束是在/ 行后
[root@k8s1 ~]# sed '2,/^\//d' /etc/fstab 6.删除以 # 开始到第一次出现 / 的行,结束是在/ 行后
[root@k8s1 ~]# sed '/^#/,/^\//d' /etc/fstab
7.显示打印以 # 开始到第一次出现 / 的行,结束是在/ 行后
[root@k8s1 ~]# sed -n '/^#/,/^\//p' /etc/fstab
8.在空行前添加 11111111111111 
[root@k8s1 ~]# sed '/^$/i \111111' /etc/fstab
[root@k8s1 ~]# sed '/^[[:space:]]*$/i \111111' /etc/fstab
9.在空行后添加 11111111111111 
[root@k8s1 ~]# sed '/^$/a \111111' /etc/fstab
[root@k8s1 ~]# sed '/^[[:space:]]*$/a \111111' /etc/fstab 10.在大写字母后添加2行
[root@k8s1 ~]# sed '/^[[:upper:]]/a \aaaaaaaaaaa\nbbbbbbbbb' /etc/issue 11. 在一个大写字母行后,把另一个文件内容追加进来。
[root@k8s1 ~]# sed '/sda2/r /etc/issue' /etc/fstab 12. 将fstab 中包含 / 的保存在/tmp/file.txt中
sed '/\//w /tmp/file.txt' /etc/fstab 13.显示匹配的行号
[root@k8s1 ~]# sed '/\//=' /etc/fstab 14. 把 /etc/issue内容 添加到fstab 第2行后
[root@k8s1 ~]# sed  '2r /etc/issue' /etc/fstab
list.txt 文件内容如下:

  docker:x:996:993:Docker User:/var/lib/docker:/sbin/nologin
  etcd:x:995:992:etcd user:/var/lib/etcd:/sbin/nologin
  puppet:x:52:52:Puppet:/var/lib/puppet:/sbin/nologin
  centos:x:2000:2000::/home/centos:/bin/bash
  nginx:x:990:9909:Nginx web server:/var/lib/nginx:/sbin/nologin

 15.删除一行中出现相同docker的行
 [root@k8s1 ~]# sed '/\(d.*r\).*\1/d' list

16.删除一行中出现相同字符的行
 [root@k8s1 ~]# sed '/\(*.\).*\1/d' list

17.替换第二个docker为Docker
[root@k8s1 ~]# sed  '/\(d.*r\).*\1/s@dockeri@Dockeri@'  list 18.替换 /etc/inittab 中 id:3:initdefault 变成数字5
[root@python tmp]# sed '/id:/s@[0-9]@5@' /etc/inittab 19.替换/etc/inittab 中 以#开头和后面有空格的行
[root@python tmp]# sed '/^#/s@^#[[:space:]]\{0,1\}@@g' inittab 20.删除/etc/inittab 中所有开头是空白的行
sed 's@^[[:space:]]\{1,\}@@g'  /etc/inittab

awk命令:
awk:报告生成工具
把文件中读取带的每一行的每个字段分别进行格式化,而后进行显示:

支持使用变量、条件判断、循环、数组

选项:
  -F:切割符
  $0:整行
  $1,$2.....:位置参数

用法格式:
awk [options] 'script' FILE...
awk [options] '/pattern/{action}' FILE...

action: print $1,$2

[root@k8s1 ~]# awk -F":" '{print $1}'  /etc/passwd

模式:
  地址定界:/pat1/,/pat2/ 一个范围        
  /pattern/ 被匹配到的行

  experssion 表达式   $3 > 2000
  >,>=,<,<=,==,!=,~(模式匹配)

  BEGIN:在遍历操作开始之前执行一次:   awk 'BEGIN{print "name"}{print $1,$2}'
  END:在遍历操作结束之后,命令退出之前退出一次。    awk 'BEGIN{print "name"}{print $1,$2}END{print “----------”}'

awk的常用四种分隔符:
输入:
  行分隔符
  字段分隔符
输出:
  行分隔符
  字段分隔符

awk内置变量之数据变量:
NR: The number of input records,awk命令所处理的记录数;如果有多个文件,这个数目会把处理的多个文件中行统一计数;
NF:Number of Field,当前记录的field个数;
FNR: 与NR不同的是,FNR用于记录正处理的行是当前这一文件中被总共处理的行数;
ARGV: 数组,保存命令行本身这个字符串,如awk '{print $0}' a.txt b.txt这个命令中,ARGV[0]保存awk,ARGV[1]保存a.txt;
ARGC: awk命令的参数的个数;
FILENAME: awk命令所处理的文件的名称;在命令中获取当前文件名
ENVIRON:当前shell环境变量及其值的关联数组;

[root@k8s1 ~]# awk -F":" '/centos/{print $0}'  /etc/passwd
centos:x::::/home/centos:/bin/bash

[root@k8s1 ~]# awk -F":" '/12/{print $0}' /etc/passwd
 mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
 games:x:12:100:games:/usr/games:/sbin/nologin

[root@k8s1 ~]# awk -F":" '$3>2000 {print $0}' /etc/passwd
 suse:x:3000:3000::/home/suse:/bin/bash

[root@k8s1 ~]# awk 'BEGIN{print "name:-------"}{print $1} END{print "-----------------"}' /etc/passwd
name:-------

......

----------

显示最后一列

[root@k8s1 ~]# awk -F":" '{print $NF}' /etc/passwd
/bin/bash
/sbin/nologin
/sbin/nologin

输入按照:号切割,输出按照+号显示

[root@k8s1 ~]# awk 'BEGIN{FS=":";OFS="+"}{print $1,$7}' /etc/passwd

root+/bin/bash

使用NR 显示总行数

[root@k8s1 ~]# awk '{print NR,$0}' /etc/passwd  /etc/fstab

使用FNR 对每个文件计数

[root@k8s1 ~]# awk '{print FNR,$0}' /etc/passwd  /etc/fstab

ARGV[0] 等于awk,ARGV[1]等于/etc/passwd,但是会循环显示 /etc/passwd

[root@k8s1 ~]# awk -F ":" '{print ARGV[0]}' /etc/passwd

可以使用BEGIN,在循环前执行

[root@k8s1 ~]# awk 'BEGIN{print ARGV[0]}'

[root@k8s1 ~]# awk -F":" '{print $1“ is a user in ”ARGV[1]}' /etc/passwd

FILENAME: awk命令所处理的文件的名称;在命令中获取当前文件名

[root@k8s1 ~]# awk '{print $0" in "FILENAME}' /etc/passwd

使用-v 自定义变量,或者直接在BEGIN中定义

[root@k8s1 ~]# awk -v num1=30 -v num2=30  'BEGIN{print num1+num2}'

[root@k8s1 ~]# awk 'BEGIN{num1=20;num2=30; print num1+num2}'

条件表达式 if

print 的区别,一个对整个行操作,一个在操作行之前操作

[root@k8s1 ~]# awk 'BEGIN{num1=231;num2=500;num1>num2?max=num1:max=num2;print max}'
500

[root@k8s1 ~]# awk 'BEGIN{num1=30;num2=55;num1>num2?max=num1:max=num2} {print max}' /etc/passwd

sed 以及 awk用法

printf

printf命令的使用格式:
printf format, item1, item2, ...

要点:
1、其与print命令的最大不同是,printf需要指定format;
2、format用于指定后面的每个item的输出格式;
3、printf语句不会自动打印换行符;\n

format格式的指示符都以%开头,后跟一个字符;如下:
%c: 显示字符的ASCII码;
%d, %i:十进制整数;
%e, %E:科学计数法显示数值;
%f: 显示浮点数;
%g, %G: 以科学计数法的格式或浮点数的格式显示数值;
%s: 显示字符串;
%u: 无符号整数;
%%: 显示%自身;

修饰符:
N: 显示宽度;
-: 左对齐;
+:显示数值符号;

例子:

[root@k8s1 ~]# awk -F":" '{printf "%-20s %s\n",$1,$NF}' /etc/passwd

sed 以及 awk用法

[root@k8s1 ~]# awk 'BEGIN{sum=55;printf "%d\n",sum}'
55

常见的模式类型:

1、Regexp: 正则表达式,格式为/regular expression/
2、expresssion: 表达式,其值非0或为非空字符时满足条件,如:$1 ~ /foo/ 或 $1 == "magedu",用运算符~(匹配)和!~(不匹配)。
3、Ranges: 指定的匹配范围,格式为pat1,pat2
4、BEGIN/END:特殊模式,仅在awk命令执行前运行一次或结束前运行一次
5、Empty(空模式):匹配任意输入行;

/正则表达式/:使用通配符的扩展集。

关系表达式:可以用下面运算符表中的关系运算符进行操作,可以是字符串或数字的比较,如$2>%1选择第二个字段比第一个字段长的行。

模式匹配表达式:

模式,模式:指定一个行的范围。该语法不能包括BEGIN和END模式。

BEGIN:让用户指定在第一条输入记录被处理之前所发生的动作,通常可在这里设置全局变量。

END:让用户在最后一条输入记录被读取之后发生的动作。

控制语句:
1 if-else
语法:awk '{if (condition) {then-body} else {[ else-body ]}}'
#

[root@k8s1 ~]# awk '{if ($3==0) {print $1, "Adminitrator";} else { print $1,"Common User"}}' /etc/passwd
[root@k8s1 ~]# awk -F":" '{if ($3==0) {printf "%-18s $s\n",$1,"is administrator"} else {printf "%-18s %s\n",$1,"is comm user"}}' /etc/passwd

sed 以及 awk用法

统计匹配的行,sum++ 就是循环一次,自身加1

[root@k8s1 ~]# awk -F: -v sum=0 '{if ($3>500) {sum++}} END{print sum}'  /etc/passwd
[root@k8s1 ~]# awk -F":" 'BEGIN{sum=0} {if($4="192.168.2.1") {sum++}} END{print sum}' fengjian

while
语法:awk  '{i=1; while (i<5) {print $i;i++}}'  file

[root@k8s1 ~]# awk -F":" '{i=1; while(i<NF) {printf "%s:",$i;i++} ;printf "\n"}' /etc/passwd

sed 以及 awk用法

[root@k8s1 ~]# awk -F":" '{i=1; while(i<NF) {if($i==3000) {print $i};i++}}' /etc/passwd

sed 以及 awk用法


for
语法: for ( variable assignment; condition; iteration process) { statement1, statement2, ...}

[root@k8s1 ~]# awk -F":" '{for(i=1;i<=NF;i++){printf "%s:",$i};printf "\n"}' /etc/passwd

sed 以及 awk用法

[root@k8s1 ~]# awk -F":" '{for(i=1;i<=NF;i+=2){printf "%s:",$i};printf "\n"}' /etc/passwd

sed 以及 awk用法


for循环还可以用来遍历数组元素:
语法: for (i in array) {statement1, statement2, ...}
awk -F: '$NF!~/^$/{BASH[$NF]++}END{for(A in BASH){printf "%15s:%i\n",A,BASH[A]}}' /etc/passwd

array[index-expression]

index-expression可以使用任意字符串;需要注意的是,如果某数据组元素事先不存在,那么在引用其时,awk会自动创建此元素并初始化为空串;因此,要判断某数据组中是否存在某元素,需要使用index in array的方式。

要遍历数组中的每一个元素,需要使用如下的特殊结构:
for (var in array) { statement1, ... }
其中,var用于引用数组下标,而不是元素值;

例子:
netstat -ant | awk '/^tcp/ {++S[$NF]} END {for(a in S) print a, S[a]}'
每出现一被/^tcp/模式匹配到的行,数组S[$NF]就加1,NF为当前匹配到的行的最后一个字段,此处用其值做为数组S的元素索引;

awk '{counts[$1]++}; END {for(url in counts) print counts[url], url}' /var/log/httpd/access_log
用法与上一个例子相同,用于统计某日志文件中IP地的访问量

从关系数组中删除数组索引需要使用delete命令。使用格式为:

delete array[index]

[root@haproxy1 ~]# netstat -an | awk '/^tcp/{state[$NF]++} END{for(A in state) {print A,state[A]}}'
sed 以及 awk用法

统计非空白行访问IP的数量

[root@tracker1 logs]# awk '!/^!/{ACCESS[$1]++} END{for(a in ACCESS) {print a,ACCESS[a]}}' access.log
sed 以及 awk用法

统计访问的路径

[root@S1PW003 logs]# awk '/GET/{res[$7]++} END{for(i in res) {print i,res[i]}}' access.log

sed 以及 awk用法

统计varnish状态码

[root@haproxy1 logs]# awk '/varnish/{code[$11]++} END{for(i in code) {print i,code[i]}}' haproxy_http.log

sed 以及 awk用法

显示为基数的行/etc/passwd,使用next

[root@k8s1 ~]# awk -F":" '{if($3%2==0) {next} else {print $1,$3}}' /etc/passwd

sed 以及 awk用法

统计当前系统上每个客户端IP的连接中处于TIME_WAIT的连接状态的个数;

[root@xinyixy_pc_006 ~]# netstat -an | awk '/TIME_WAIT/{laststr[$NF]++} END{for(i in laststr) {print i,laststr[i]}}'

统计ps aux命令执行时,当前系统上各用户的进程的个数;

root@xinyixy_pc_006 ~]# ps aux | awk '{state[$8]++}END{for(i in state) {printf "%-15s %s\n",i,state[i]}}'

awk的内置函数

awk '{split(分割的字段, 数组名称 ,分割符)'}

功能:将string表示的字符串以fieldsep为分隔符进行分隔,并将分隔后的结果保存至array为名的数组中;数组下标为从1开始的序列;

# netstat -ant | awk '/:80\>/{split($5,clients,":");IP[clients[1]]++}END{for(i in IP){print IP[i],i}}' | sort -rn | head -50

# netstat -tan | awk '/:80\>/{split($5,clients,":");ip[clients[4]]++}END{for(a in ip) print ip[a],a}' | sort -rn | head -50

# df -lh | awk '!/^File/{split($5,percent,"%");if(percent[1]>=20){print $1}}'

[root@xinyixy_ha_001 ~]# netstat -anpt | awk '{split($7,program,"/");res[program[2]]++} END{for(i in res) {print res[i],i}}'

length([string])
功能:返回string字符串中字符的个数;

substr(string, start [, length])
功能:取string字符串中的子串,从start开始,取length个;start从1开始计数;

system(command)
功能:执行系统command并将结果返回至awk命令

systime()
功能:取系统当前时间

tolower(s)
功能:将s中的所有字母转为小写

toupper(s)
功能:将s中的所有字母转为大写