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

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

 # cat /etc/passwd |awk -F: '{if ($3>100) name[count++]=$1}END{for (i=0;i<count;i++) print i,name[i]}'
 # netstat -nap  |awk '$6~/CONNECT/{sum[$6]++}END{for (i in sum)print i,sum[i]}'
原文地址:https://www.cnblogs.com/xiaobaozi-95/p/9675539.html