【Linux】【Shell】Shell 正则表达式

研究学习 Linux Shell 的系列文章.

这篇文章主要讲正则表达式.

1. 正则表达式

1.1 正则表达式的概念

 正则表达式是用于描述字符排列和匹配模式的一种语法规则. 它主要用于字符串的模式分割、匹配、查找及替换操作.

1.2 正则表达式与通配符
  • 正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。grep、awk、sed 等命令可以支持正则表达式。
  • 通配符用来匹配符合条件的文件名,通配符是完全匹配。ls、find、cp 这些命令不支持正则表达式,所以只能使用 shell 自己的通配符来进行匹配了。
    • *:匹配任意内容
    • ?:匹配任意一个内容
    • []:匹配中括号中的一个字符
user@ubuntu:~# touch abc.txt adc.txt
user@ubuntu:~# ls
abc.txt  adc.txt  anaconda-ks.cfg
user@ubuntu:~# ls a*
abc.txt  adc.txt  anaconda-ks.cfg
user@ubuntu:~# ls a?c.txt
abc.txt  adc.txt
user@ubuntu:~# ls a[bd]c.txt
abc.txt  adc.txt
1.3 基础正则表达式

正则表达式分为:

  • 基础正则表达式
  • 扩展正则表达式

主要使用基础正则表达式,扩展正则表达式这里不介绍

元字符作用
*前一个字符匹配0次或任意多次.
.匹配除了换行符外任意一个字符.
^匹配行首. 例如:^hello 会匹配以 hello 开头的行.
$匹配行尾. 例如:hello& 会匹配以 hello 结尾的行.
[]匹配中括号中指定的任意一个字符,制匹配一个字符. 例如:[aoeiu] 匹配任意一个元音字母,[0-9] 匹配任意一位数字,[a-z][0-9]匹配小写字和一位数字构成的两位字符.
[^]匹配除中括号的字符以外的任意一个字符. 例如:[^0-9] 匹配任意一位非数字字符,[^a-z] 表示任意一位非小写字母.
\转义符. 用于取消特殊符号的含义.
\{n\}表示其前面的字符恰好出现 n 次. 例如:[0-9]\{4\} 匹配 4 位数字,[1][3-8][0-9]\{9\} 匹配手机号码.
\{n,\}表示其前面的字符出现不小于 n 次. 例如:[0-9]\{2,\}表示两位及以上的数字.
\{n,m\}表示其前面的字符至少出现 n 次,最多出现 m 次. 例如:[a-z]\{6,8\} 匹配6到8位的小写字母.

?<> 是扩展正则表达式.

"a*"
# 匹配所有内容,包括空白行
“aa*”
# 匹配至少包含一个a的行
“aaa*”
# 匹配最少包含两个连续a的字符串
“aaaaa*”
# 匹配最少包含四个连续a的字符串
1.4 几个例子

1. 匹配日期格式 YYYY-MM-DD

[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}

2. 匹配IP地址

[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\

2. 字符截取命令

2.1 grep 命令

grep 命令用来行提取字符串:

grep [选项] [正则表达式] [文件]

常用选项:

  • -v:反匹配,找出不匹配的行
  • -n:显示行号
  • -i:不区分大小写
  • --color:[ always | nerver | auto ] 颜色高亮
user@ubuntu:~# useradd user1
user@ubuntu:~# useradd user2
user@ubuntu:~# grep "bin/bash" /etc/passwd
root:x:0:0:root:/root:/bin/bash
lucifer:x:1000:1000::/home/lucifer:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
user@ubuntu:~# grep -n "bin/bash" /etc/passwd
1:root:x:0:0:root:/root:/bin/bash
26:lucifer:x:1000:1000::/home/lucifer:/bin/bash
27:user1:x:1001:1001::/home/user1:/bin/bash
28:user2:x:1002:1002::/home/user2:/bin/bash
user@ubuntu:~# grep "bin/bash" /etc/passwd | grep -v "root"
lucifer:x:1000:1000::/home/lucifer:/bin/bash
user1:x:1001:1001::/home/user1:/bin/bash
user2:x:1002:1002::/home/user2:/bin/bash
2.2 cut 命令

cut 命令用来列提取字符串:

cut [选项] 文件名

选项:

  • -f 列号:提取第几列
  • -d 分隔符:按照指定分隔符分割列

student.txt 文件如下,其中使用制表符

ID	Name	Gender	Mark
1	Ford	M	    85
2	White	M	    60
3	Clyde	M	    70
user@ubuntu:~# cut -f 2 student.txt 
Name
Ford
White
Clyde
user@ubuntu:~# cut -f 2,4 student.txt 
Name	Mark
Ford	85
White	60
Clyde	70
user@ubuntu:~# grep "bin/bash" /etc/passwd | grep -v "root" | cut -f 1 -d ":"
lucifer
user1
user2

缺陷:适合以制表符为分隔符的文档,以空格为分隔符时难以实现需求.

user@ubuntu:~# df -h | cut -f 5
Filesystem      Size  Used Avail Use% Mounted on
devtmpfs        899M     0  899M   0% /dev
tmpfs           910M     0  910M   0% /dev/shm
tmpfs           910M  9.6M  901M   2% /run
tmpfs           910M     0  910M   0% /sys/fs/cgroup
/dev/sda3        19G  1.5G   18G   8% /
/dev/sda1       488M  117M  336M  26% /boot
tmpfs           182M     0  182M   0% /run/user/0
user@ubuntu:~# df -h | cut -f 1,3 -d " "
Filesystem 
devtmpfs 
tmpfs 
tmpfs 
tmpfs 
/dev/sda3 
/dev/sda1 
tmpfs
2.3 printf 命令
printf '输出类型输出格式' 输出内容
  • 输出类型:
    • %ns:输出字符串. n 是数字指代输出几个字符.
    • %ni:输出整数. n 是数字指代输出几个数字
    • %m.nf:输出浮点数. m 和 n 是数字,指代输出的整数位和小数位,如 %8.2f 代表共输出 8 位数,其中 2 位是小数,6位是整数.
  • 输出格式:
    • \a:输出警告声音
    • \b:输出退格键,也就是 Backspace 键
    • \f:清除屏幕
    • \n:换行
    • \r:回车,也就是 Enter 键
    • \t:水平输出退格键,也就是 Tab 键
    • \v:垂直输出退格键,也就是 Tab 键
user@ubuntu:~# printf %s 1 2 3 4 5 6
123456user@ubuntu:~#
user@ubuntu:~# printf %s %s %s 1 2 3 4 5 6
%s%s123456user@ubuntu:~#
user@ubuntu:~# printf '%s %s %s' 1 2 3 4 5 6
1 2 34 5 6user@ubuntu:~#
user@ubuntu:~# printf '%s %s %s\n' 1 2 3 4 5 6
1 2 3
4 5 6
user@ubuntu:~# printf '%s' $(cat student.txt)
IDNameGenderMark1FordM852WhiteM603ClydeM70user@ubuntu:~#
user@ubuntu:~# printf '%s\t%s\t%s\t%s\n' $(cat student.txt)
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
3	Clyde	M	70

在 awk 命令的输出中支持 print 和 printf 命令

  • print:print 会在每个输出之后自动加入一个换行符(Linux 默认没有 print 命令)
  • printf:printf 是标准格式输出命令,并不会自动加入换行符,如果需要换行,需要手工加入换行符
2.4 awk 命令
awk '条件1{动作1} 条件2{动作2}...' 文件名
  • 条件(Pattern):
    • 一般使用关系表达式作为条件
    • x>10 判断变量x是否大于10
    • x>=10 大于等于
    • x<=10 小于等于
  • 动作(Action):
    • 格式化输出
    • 流程控制语句

逐行执行,$n 表示第 n 列. {动作} 前有条件条件成立执行{动作},若{动作} 前无条件{动作}直接执行.

user@ubuntu:~# awk '{printf $2 "\t" $4 "\n"}' student.txt 
Name	Mark
Ford	85
White	60
Clyde	70

printf 是标准输出,print 自带换行符 \n.

user@ubuntu:~# awk '{print $2 "\t" $4}' student.txt 
Name	Mark
Ford	85
White	60
Clyde	70
user@ubuntu:~# awk '{printf $2 "\t" $4}' student.txt 
Name	MarkFord	85White	60Clyde	70user@ubuntu:~#
user@ubuntu:~# df -h | awk '{print $1 "\t" $3}'
Filesystem	Used
devtmpfs	0
tmpfs	0
tmpfs	9.6M
tmpfs	0
/dev/sda3	1.5G
/dev/sda1	117M
tmpfs	0
user@ubuntu:~# df -h | grep '/dev/sda' | awk '{print $5}'
8%
26%
user@ubuntu:~# df -h | grep '/dev/sda' | awk '{print $5}' | cut -d "%" -f 1
8
26

BEGIN 和 END 条件.

user@ubuntu:~# awk 'BEGIN{print "test"} {print $2 "\t" $4}' student.txt 
test
Name	Mark
Ford	85
White	60
Clyde	70
user@ubuntu:~# awk 'END{print "test"} {print $2 "\t" $4}' student.txt
Name	Mark
Ford	85
White	60
Clyde	70
test

BEGIN 搭配 FS 内置变量设置分隔符,BEGIN 表示在读取内容之前执行动作.

user@ubuntu:~# cat /etc/passwd | grep /bin/bash | awk '{FS=":"}{print $1 "\t" $3}'
root:x:0:0:root:/root:/bin/bash	
lucifer	1000
user1	1001
user2	1002
user@ubuntu:~# cat /etc/passwd | grep /bin/bash | awk 'BEGIN{FS=":"}{print $1 "\t" $3}'
root	0
lucifer	1000
user1	1001
user2	1002

关系运算符

user@ubuntu:~# cat student.txt | grep -v Name | awk '$4>=70{print $2}'
Ford
Clyde
2.5 sed 命令

sed 是一种几乎包括所有 UNIX 平台(包括 Linux)的轻量级流编辑器. sed 主要是用来将数据进行选取、替换、删除、新增的命令.

sed [选项] ‘[动作]’ 文件名

选项:

  • -n:一般 sed 命令会把所有数据都输出到屏幕,如果加入次选项则只会把经过 sed 命令处理的行输出到屏幕.
  • -e:允许对输入数据应用多条命令编辑
  • -i:用 sed 命令修改结果直接修改读取数据的文件,而不是由屏幕输出.

动作:

  • a:追加,在当前行后添加一行或多行
  • c:行替换,用 c 后面的字符串替换原数据行
  • i:插入,在当期行前插入一行或多行.
  • d:删除,删除指定的行
  • p:打印,输出指定的行.
  • s:字串替换,用一个字符串替换另外一个字符串. 格式为 “行范围s/旧字串/新字串/g”(和 vim 中的替换格式类似).
user@ubuntu:~# sed '2p' student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
1	Ford	M	85
2	White	M	60
3	Clyde	M	70
user@ubuntu:~# sed -n '2p' student.txt 
1	Ford	M	85
user@ubuntu:~# sed '2d' student.txt 
ID	Name	Gender	Mark
2	White	M	60
3	Clyde	M	70
user@ubuntu:~# sed '2,4d' student.txt 
ID	Name	Gender	Mark
user@ubuntu:~# sed '2i test' student.txt 
ID	Name	Gender	Mark
test
1	Ford	M	85
2	White	M	60
3	Clyde	M	70
user@ubuntu:~# sed '2a test' student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
test
2	White	M	60
3	Clyde	M	70
user@ubuntu:~# sed '4c Clyde is a fool' student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
Clyde is a fool
user@ubuntu:~# sed '4s/70/100/g' student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
3	Clyde	M	100
user@ubuntu:~# cat student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
3	Clyde	M	70
user@ubuntu:~# sed -i '4s/70/100/g' student.txt 
user@ubuntu:~# cat student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
3	Clyde	M	100
user@ubuntu:~# cat student.txt 
ID	Name	Gender	Mark
1	Ford	M	85
2	White	M	60
3	Clyde	M	100
user@ubuntu:~# sed -e 's/Ford//g;s/White/Green/g' student.txt 
ID	Name	Gender	Mark
1		M	85
2	Green	M	60
3	Clyde	M	100

3. 字符处理命令

3.1 sort 命令
sort [选项] 文件名

选项:

  • -f:忽略大小写
  • -n:以数值型进行排序,默认使用字符串型排序
  • -r:反向排序
  • -t:指定分隔符,默认分隔符是制表符
  • -k n[,m]:按照指定的字段范围排序. 从第 n 字段开始,m 字段结束(默认到行尾)
sort -n -t ":" -k 3,3 /etc/passwd
3.2 wc 命令
wc [选项] 文件

选项:

  • -l:只统计行数
  • -w:只统计单词数
  • -m:只统级字符数
  • 3
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值