研究学习 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:只统级字符数