sed & awk sed awk
基本正则
. 匹配任意一个字符,除了换行符,在sed中不能匹配换行符,但是在awk中可以匹配换行符
* 表示前边字符有0个或多个
[] [a-z] [0-9] [^0-9] 非数字的
^ 行首 ^abc:以abc开头
$ 行尾 world$:以world结尾
{}
{2}:表示前边字符的重复次数是2。
{2,}:表示前边字符的重复次数至少是2,也就是大于等于2。
{2,9}:表示前边字符的重复次数大于2但小于9。
扩展正则
? 前置字符有0个或1个
+ 前置字符有1个或多个
| 或
() 分组
{} 和基本正则表达式中的大括号意义是一样的,只不过在使用时不用加""转义符号。
echo
-e 处理特殊字符
# echo -e '123 456'
123 456
# echo -e '123
456'
123
456
sed [选项] ‘command’ 文件名称
选项:-n,-e,-i,-f,-r选项。
command:[地址1,地址2] [函数] [参数(标记)]
常用选项:
-n 选项后被设定为安静模式,也就是不会输出默认打印信息 。经常结合p使用
# echo -e 'hello
world' |sed 's/hello/H/'
H
world
# echo -e 'hello
world' |sed -n 's/hello/H/' #加上-n 不打印
# echo -e 'hello
world' |sed -n 's/hello/H/p' # -n加上p标记,只会把匹配并修改的内容打印出来
H
-e 用sed执行多条命令
# echo -e 'hello
world' |sed -e 's/hello/H/' -e 's/world/W/'
H
W
# echo -e 'hello
world' |sed 's/hello/H/;s/world/W/' #等同于用分号连接多个子命令
H
W
-i 修改源文件
# sed -i.bak '/while/d' test.py # 修改源文件 源文件备份为.bak
打印
p 打印
# nl /etc/passwd | sed -n '10,20p' 打印第10行-20行
....
# cat /etc/my.cnf |sed -n '/log-error/p' 打印包含log-error的行
# nl /etc/passwd | sed -n '/operator/,/abrt/p' 匹配operator到abrt之间的所有行
# nl /etc/passwd | sed -n '10!p' 不打印第10行
# nl /etc/passwd | sed -n '10,20!p' 不打印第10-20行
# nl /etc/passwd | sed -n '1~2p' 间隔行 打印1,3,5....行
操作命令
a 追加
# echo -e 'hello
world' |sed '/world/a ---' #在world这行后面增加
hello
world
---
# echo -e 'hello
world' |sed '1,2a ---' #1-5行后面 每一行都增加
hello
---
world
---
# echo -e 'hello
world' |sed '$a ---' #在文末增加
hello
world
---
r 把一个文件的内容追加到指定行下面
# cat a.txt
aaaaa
# echo -e 'hello
world' | sed '2r a.txt'
hello
world
aaaaa
i 插入
# echo -e 'hello world' |sed '1i +++' #第1行前面插入
# echo -e 'hello
world' |sed '1,2i +++' #第1-2行每一行前面插入
+++
hello
+++
world
c 替代
# echo -e 'hello
world' |sed '/hello/c xxx' #把匹配的行内容替换成xxx
xxx
world
# echo -e 'hello
world' |sed '1,$c xxx' #把1-末行内容作为一个整体替换成xxx
xxx
d 删除
# cat /etc/passwd |sed '1,40d' # 删除1-40行
# cat /etc/my.cnf |sed '/^$/d' #删除空行
# cat /etc/passwd |sed '/rpc/,/salt/d' #删除匹配到rpc行和salt行之间的所有行
s 替换
g全局
# echo -e 'falsefalse
true' |sed 's/false/FALSE/g'
FALSEFALSE
true
# ifconfig | sed -n '/broadcast/p' |sed 's/inet//' |sed 's/netmask.*//'
& 表示正则表达式匹配的整个结果集
# echo 'hello world' |sed 's/hello/11&22/' # &符号
11hello22 world
-r 支持扩展正则表达式
()分组
# echo 'hello 123 world' |sed -r 's/([a-z]+)( [0-9]+ )([a-z]+)/132/'
helloworld 123
awk
一次处理一行内容,可以对每行进行切片处理
格式: awk [option] 'pattern{awk 操作命令}' file
pattern:正则表达式,逻辑判断式
操作命令:内置函数:print() printf()
控制指令:if(){...} else{...},while(){...}
awk 内置变量
$0: 整个当前行
$1: 每行第一个字段
分隔符
-F 如果不指定就会默认使用空格
# cat /etc/passwd |awk -F: '{print $3}' #打印第三个字段
# cat /etc/passwd |awk -F: '{print $1" "$7}' #打印第1,7字段,并以 分割
NR:每行的记录号 行号 Number of Record
NF: 字段数量变量 列号 Number of Fileds
# cat /etc/passwd |awk -F: '{print "line: "NR,"column: "NF,"user: "$1}'
条件判断 if
打印用户id大于100的行号和用户名
# cat /etc/passwd |awk -F: '{if ($3>100) print $1}'
打印包含True的行
# cat server.py |awk '/True/{print $0}'
用sed
# cat server.py |sed -n '/True/p'
patter 逻辑判断式
~,!~ 匹配正则表达式
== ,!= ,< , > 判断逻辑表达式
# df -h | awk 'NR!=1{print $1,$4}'
# cat /etc/passwd |awk -F: '$1=="root" {print $0}' #"root"双引号
# cat /etc/passwd |awk -F: '$3 > 100 && $3 < 1000 {print $1,$3}' # 100<uid<1000
# cat /etc/passwd |awk -F ':' '$1~/^m.*/{print $1}' #第一个字段以m开头
# cat test.log | awk '{if($0~/^$/) print NR}' #打印空行的行号
扩展格式 BEGIN END
awk [options] 'BEGIN{print "start"} pattern{commands} END{print "end"}' file
BEGIN{ 执行前的语句 } {处理每一行时要执行的语句} END { 处理完所有的行后要执行的语句 }
# cat /etc/passwd |awk -F: 'BEGIN{print "------start-----"}$3>1000{print $1":"$3}END{print "---end-------"}'
------start-----
git:1001
salt:1002
---end-------
# cat /etc/passwd |awk -F: 'BEGIN{print "Line Col User"}{print NR" "NF" "$1}END{print "------"}'
Line Col User
1 7 root
2 7 bin
------
统计文件夹大小
# ls -l |awk 'BEGIN{s=0}{s+=$5}END{print "size is:"s/1024/1024"M"}'
size is:382.935M
# ls -l |awk '{s+=$5}END{print "size is:"s/1024/1024"M"}' #awk里面变量初始值默认0,可以不写BEGIN初始化
size is:382.935M
统计passwd账户总人数
# cat /etc/passwd |awk -F: '$1!~/^$/{sum++}END{print "count: "sum}' #排除空行
count: 42
统计UID大于100的用户名
# cat /etc/passwd |awk -F: '$3>100 {sum+=1}END{print sum}'
20