4.6 Shell 三剑客

1、正则表达式
a. 概念

正则表达式(或称Regular Expression,简称RE),是用于描述字符排列和匹配模式的一种语法规则。它主要用于字符串的分割,匹配、査找及替换操作。即正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

b. 工作流程

正则表达式是用来匹配文件中的字符串的方法。它会先把个文整本分成一行一行的字符串,然后从每行字符串中搜索是否有符合正则表达式规则的字符串,如果有则匹配成功,如果没有则匹配失败。

c. 正则与通配符

正则表达式用来在文件中匹配符合条件的字符串,通配符用来匹配符合条件的文件名, 这种区别只在 Shell 中适用,因为用来在文件中搜索字符串的命令,如 grep、awk、sed、vi 等可以支持正则表达式,而在系统中搜索文件的命令,如 ls、find、cp 等不支持正则表达式,所以只能使用 Shell 自己的通配符来进行匹配。

d. 基础元字符

在正则表达式中,我们把用于匹配的特殊符号又称作元字符。在shell中,元字 符又分为基础元字符(BRE)和扩展元字符(ERE)。

*

匹配前面的子表达式零次或多次。

.

匹配除换行符(\n、\r)之外的任何单个字符

.*

匹配任意长度字符串

^

匹配行首。^hello 会匹配以 hello 开头的行

$

匹配行尾。hello$ 会匹配以 hello 结尾的行

^&

匹配空行

[]

匹配中括号中指定的任意一个字符,而且只匹配一个字符。[0-9] 匹配任意一位数字, [a-zA-Z] 匹配任意一位英文字母

[^]

匹配除了中括号字符以外的任意一个字符,[^ab^c] 匹配除了a、b、^、c以外的任意单个字符

\

转义符,用于取消特殊符号的含义,使该特殊字符成为普通字符。

{n}

匹配连续出现字符的行。n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个o

{n,}

匹配连续出现字符的行。n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有o。

{n,m}

匹配连续出现字符的行。m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 将匹配 "fooooood" 中的前三个o

\d

匹配一个数字字符。等价于[0-9]

\D

匹配一个非数字字符。等价于[^0-9]

\w

匹配字母、数字、下划线。等价于'[A-Za-z0-9_]'

\W

匹配任何非单词字符。等价于“[^A-Za-z0-9_]”

\b

匹配一个单词边界。'er\b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'

\B

匹配单词非边界。'er\B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'

\< \>

匹配词(word)的开始(\<)和结束(\>),例如正则表达式\<the\>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。

e. 扩展元字符

正则表达式除了支持基础元字符,还支持"+"、"?"、"|"、"()"等元字符,默认linux是支持这些元字符,只不过grep不支持,如果grep想要使用这些元字符,可以使用egrep 或 grep -E 命令。

字符

描述

+

匹配前面的一个字符或子表达式1次或任意多次,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。等价于 {1,}

?

匹配前面的一个字符或子表达式零次或一次,"do(es)?" 可以匹配 "do"或"does"。? 等价于{0,1}

|

表示或,“was|his”既会匹配包含“was”的行,或匹配包含“his”的行

()

标记一个子表达式的开始和结束位置,将括号里的内容看成是一个整体,“(dog)+”会匹配“dog” “dogdog” “dogdogdog”等

f. 非打印字符

非打印字符也可以是正则表达式的组成部分

字符

描述

\cx

匹配由x指明的控制字符。例如, \cM 匹配一个 Control-M 或回车符。x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。

\f

匹配一个换页符。等价于\x0c 和 \cL。

\n

匹配一个换行符。等价于\x0a 和 \cJ。

\r

匹配一个回车符。等价于\x0d 和 \cM。

\t

匹配一个制表符。等价于\x09 和 \cI。

\v

匹配一个垂直制表符。等价于\x0b 和 \cK

\s

匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。

\S

匹配任何非空白字符。等价于[^ \f\n\r\t\v]。

g. 修饰符(标记)

正则表达式的标记用于指定额外的匹配策略, 标记不写在正则表达式里,标记位于表达式之外

字符

描述

i

将匹配设置为不区分大小写,搜索时不区分大小写: A 和 a 没有区别

g

查找所有的匹配项

m

使边界字符^ 和 $ 匹配每一行的开头和结尾,记住是多行,而不是整个字符串的开头和结尾

s

默认情况下的圆点. 是匹配除换行符 \n 之外的任何字符,加上 s 修饰符之后, . 中包含换行符 \n。

h. 字符优先级

正则表达式从左到右进行计算,并遵循优先级顺序,这与算术表达式非常类似,相同优先级的从左到右进行运算,不同优先级的运算先高后低。

字符

描述

\

转义符

(), (?:), (?=), []

圆括号和方括号

*, +, ?, {n}, {n,}, {n,m}

限定符

^, $, \任何元字符、任何字符

位置和顺序

|

"或"操作

2、三剑客之 grep
  • 描述:过滤
  • 语法:grep [选项] 字符

-E, --extended-regexp PATTERN 是一个可扩展的正则表达式(缩写为 ERE)

-G, --basic-regexp PATTERN 是一个基本正则表达式(缩写为 BRE)

-P, --perl-regexp PATTERN 是一个 Perl 正则表达式

-n 显示匹配行的行号

-v 显示不包含关键字的行

-i 忽略大小写

-l 一般和-r联用, 只显示包含关键字的文件的名字, 而不是显示文件内容

-r 递归检索

-w 按照单个词语的方式匹配

# 过滤掉空行和注释行
grep -vE "^#|^$" test.txt

# 过滤以数字结尾的行
grep -E "[0-9]$" test.txt | grep -P "\d$" test.txt

# 过滤出以字母开头的行
grep -E "^[a-zA-Z]" test.txt | grep -iE "^[a-z]" test.txt

# 过滤出带 the 的行。
grep -E "(the)"  test.txt 

# 过滤出 the 单词
grep -E "\<the\>" test.txt

# 过滤 连续出现2次d 的行
grep -E "d{2}" test.txt

# 过滤出 至少连续出现3次r 的行
grep -E "r{3,}" test.txt | grep -P "r{3,}" test.txt

# 过滤手机号
grep -E "\<1[3|4|5|6|7|8][0-9]{9}\>" phone.txt 
3、三剑客之 sed
  • 描述:采用的是流编辑模式,无交互式的方式来编辑文本。
  • 语法:sed [选项] [动作指令] filename

选项:

-n 默认情况下,sed 会在动作指令执行完毕后,自动输出处理后的内 容, 而该选项会屏蔽默认输出。

-e 执行多个sed指令

-i 此选项会直接修改源文件,要慎用,修改前建议先备份源文件。

-i.bak 编辑源文件的同时创造.bak的备份

-r 使用扩展的正则表达式

动作指令:

p 打印,输出指定的行

s 替换,替换指定字符串

d 删除,删除行

a 增加行,在当前行下面插入文件

i 增加行,在当前行上面插入文件

c 把选定的行改为新的指定的文本

r 读取文件,即用于将一个独立文件的数据插入到当前数据流的指定位置

w 另存为

注意:搜索条件要使用“/…/”括起来

-----------------------------------------

我们知道,vim/vi 采用的是交互式文本编辑模式,你可以用键盘命令来交互性地插入、删除或替换数据中的文本。

sed全名叫stream editor,流编辑器。它采用的是流编辑模式,最明显的特点是,在sed 处理数据之前,需要预先提供一组规则,sed会按照此规则来编辑数据,实现无交互式编辑数据。

sed也是支持正则表达式的,如果要使用扩展正则加参数-r

sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。

  • 首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间)。
  • 然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。
  • sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。
  • 处理完输入文件的最后一行后,sed便结束运行。
a. 打印_p

# 查询test1.txt文件cat这一行
sed '/cat/p' test1.txt 

查询test1.txt文件cat这一行,禁止默认输出
sed -n '/cat/p' test1.txt
  • p指令是默认输出所有行,"-n"选项,禁止默认输出

# 查看test1.txt文件第2行
cat -n test1.txt | sed -n '2p'

# 一次打印多行
cat -n test1.txt | sed -n -e '2p' -e '4,6p'

b. 替换_s
  • 语法:sed 's/要被替换的字串/新的字串/g' 文件
  • 注意:sed 默认不会直接修改源文件数据,想要修改源文件请添加-i选项
# 把test1.txt文件中的name替换为names
sed 's/name/James/g' test1.txt

# 将原文件中的name全部替换为 Tom
sed -i 's/name/Tom/g' test1.txt

# 查看原文件
cat test1.txt

# 注释test1.txt第4-6行
sed -i '4,6s/^/#/g' test1.txt
cat -n test1.txt

# 取消文件中4到6行的注释
sed -i 's/^#//g' test1.txt 
cat -n test1.txt 

# 使用取得ens33网卡IP地址
ifconfig ens33 | sed -n '/netmask/p' | sed -e 's/^.*inet//' -e 's/netmask.*$//'

c. 删除_d
# 删除cat中的 第二行
cat -n test1.txt | sed '2d'

# 删除test1.txt源文件5到最后一行
sed -i '5,$d' test1.txt

# 根据匹配内容删除行
sed -i '/cat/d' test1.txt

d. 添加_a,i
  • i(insert插入),在指定行前面插入一行
  • a(append附加),在指定行后面添加一行
# 在第1行前面插入一行
sed -i '1i\hello first' test1.txt
cat -n test1.txt 

# 在最后一行下面添加一行
sed -i '$a\hello last' test1.txt
cat -n test1.txt

# 在2-4行上面分别添加一行"=================="
sed -i '2,4i\==============' test1.txt 
cat -n test1.txt

e. 替换整行_c

注意:"c"动作是进行整行替换的,如果仅仅想替换行中的部分数据,就要使用"s"动作

# 把所有=号开头的行修改为#
sed -i '/^=/c\############' test1.txt 
cat -n test1.txt 

# 永久关闭selinux
sed -i '/SELINUX=enforcing/c\SELINUX=disabled' /etc/selinux/config
sed -n '/SELINUX=/p' /etc/selinux/config

f. 读取_r
# 将test3文件中的内容 读取到test1文件的尾部
sed -i '$r./test3.txt' test1.txt 
cat test1.txt 

g. 写入_w
# 将test1中的内容 写入到 test3文件中
sed -i 'w./test3.txt' test1.txt
cat -n test3.txt 

4、三剑客之 awk

awk命名: Aho、Weingberger 和 Kernighan三个人的姓的缩写。

awk是gawk的链接文件,awk是一种优良的文本处理工具,Linux及Unix环境中现有的功能最强大的数据处理引擎之一。相较于sed 常常作用于一整个行的处理, awk 则比较倾向于一行当中分成数个字段来处理。

awk 命令也是逐行扫描文件,寻找含有目标文本的行,如果匹配成功,则会在该行上执行用户想要的操作;反之,则不对行做任何处理。

语法:awk [options] '匹配规则{执行命令}' filename

-F 指定分隔符,awk使用空格或tab键作为默认分隔符

-v key=values在执行处理过程之前,设置一个变量

awk保留字

BEGIN

在awk程序一开始,尚未读取任何数据之前执行。BEGIN 后的动作只在程序开始时执行一次

awk保留字

END

在awk程序处理完所有数据,即将结束时执行。END 后的动作只在程序结束时执行一次

关系运算符

>

大于

<

小于

>=

大于等于

<=

小于等于

==

等于。用于判断两个值是否相等

!=

不等于

匹配表达式

~(匹配)

value ~ /regexp/ 如果value匹配/regexp/,则返回真

!~(不匹配)

value !~ /regexp/ 如果value不匹配/regexp/,则返回真

正则表达式

/正则表达式/

如果在“//”中可以写入字符,则也可以支持正则表达式

逻辑运算符

&&

逻辑与

||

逻辑或

a. 完整格式

awk [options] 'BEGIN{ print "start" } 匹配规则{ commands } END{ print "end" }' filename

awk会自动给一行中的每个数据字段分配一个变量。

$0

代表整个文本行

$1

代表文本行中的第 1 个数据字段

$2

代表文本行中的第 2 个数据字段

$n

代表文本行中的第 n 个数据字段

BEGIN 的执行时机是在 awk 程序一开始,尚未读取任何数据之前。一旦BEGIN后的动作执行一次,当awk开始从文件中读入数据时,BEGIN 的条件就不再成立,所以BEGIN定义的动作只能被执行一次。通过BEGIN开始块我们可以用来设置变量,设置标题。

END也是awk的保留字,不过刚好和 BEGIN 相反。END 是在 awk 程序处理完所有数据,即将结束时执行的。END 后的动作只在程序结束时执行一次

# 查看uid>1000的用户
awk -F ":" 'BEGIN{print "user\t\tbash"}$3>1000{print $1"\t\t"$7}' /etc/passwd

# 查看uid>1000的用户并在行尾输出结束标志
awk -F ":" 'BEGIN{print "user\t\tbash"} $3>1000{print $1"\t\t"$7} END{print "===================================\n            the end\n==================================="}' /etc/passwd

# 打印/etc/passwd登陆shell为/bin/bash的用户
awk -F ":" '$7 ~ /bash$/{print $1"==>"$7}' /etc/passwd

# 使用awk过滤IP地址
ifconfig ens33 | awk '/netmask/{print $2}'

b. awk 自定义变量
# 统计用户数量,在执行过程之前设置变量
 awk -F ":" -v column1='统计用户数' -v count=0 'BEGIN{print column1} {count++} END{print "user_count:",count}' /etc/passwd

c. awk 内置变量

内置变量

含义

$0

这个变量包含执行过程中当前行的文本内容

$n

当前记录(当前行)的第n个字段,比如n为1表示第一个字段

FILENAME

当前输入文件的名

FS

字段分隔符(默认是任何空格)

NF

表示字段数,在执行过程中对应于当前的字段数

NR

表示记录数,在执行过程中对应于当前的行号

FNR

各文件分别计数的行号

# 打印/etc/passwd每行有多少列
awk -F ":" '/^root/{print NF}' /etc/passwd		# 输出-> 7

# 过滤test1.txt带dog的行及行号
awk '/dog/{print NR,$0}' test1.txt

# awk多文件扫描,FNR每个文件单独统计行号
awk '{print NR,$0}' test1.txt test3.txt

# 统计当前内存的使用率
free -m | awk '/Mem/{printf "%.2f%%\n",(1-$4/$2)*100}'

d. awk if判断

单分支

if (条件) print

双分支

if(条件){print}else{print}

多分支

if(条件){print}else if(条件){print}else{print}

# 统计分区使用率,输出超过50%的分区信息
e. awk while循环

while(条件){语句}

# 计算每个学生的总分数
awk '$1 !~ /姓名/{total=0;i=5;while(i<=NF){total+=$i;i++};print $1,"  总分数:",total}' score.txt
  • $1 !~ /姓名/:过滤掉表格的头部
  • 定义变量:总分-total,内置变量NF代表有7部分,总分需要使用第5-7部分(各科成绩)
  • 循环起始条件从5开始7结束,$i,如果i=5 则 $5是awk的第五列,也就是语文成绩,以此类推。

f. awk for循环

for(变量赋值;条件;迭代){命令}

# 遍历数组中的变量
awk 'BEGIN{name[0]="齐桓公";name[1]="楚庄王";name[2]="宋襄公";name[3]="晋文公";name[4]="秦穆公";for(i in name){print i,name[i]}}'

g. awk 数组

array[“index”]++ 每循环一次这个索引所对应的元素次数加1

# 统计Listen和Estableshed出现的次数
netstat -antu | awk '/tcp/{state[$NF]++} END{for(i in state){print i,state[i]}}'

-------------------------------

# 统计相同的网站出现的次数
awk -F "//" '{web[$NF]++} END{for(i in web){print web[i],i}}' ipcom.txt

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值