在Linux Shell 编程中,我们常需要用到 正则表达式 进行 文件的匹配
在本篇文章中,我们对Linux shell 中的正则表达式 做一个总结,方便之后的shell 编写。
参考文章:
shell编程之正则表达式
https://www.cnblogs.com/whc-uestc/p/4700360.html
shell script 在if 的判断条件正则表达式=~中引号问题
https://www.cnblogs.com/gaochsh/p/6901807.html
shell 正则表达式详细整理
https://www.jb51.net/article/94354.htm
1. 什么是正则表达式
2. 什么是通配符
3. 通配符 与 正则表达式 的区别
4. 基本正则表达式语法
5. 常用的正则表达式
6. 示例,Linux Shell 脚本中正则表达式
===========================================
什么是正则表达式
正则表达式是用于描述字符排列和匹配模式的一种语法规则。
在很多程序设计语言中都支持利用正则表达式来进行字符串的操作,不同语言中的正则表达式略有不同,但是毕竟都是正则,其本质思想都是一致的,当我们掌握了shell中的正则后,再去看python或者perl里面的正则表达式时,会发现其实都是一样的东东。
在shell的一些命令中,有些并不支持正则表达式,但是它们支持Linux里面的通配符,那么通配符又是什么东东呢,它跟正则表达式又有什么关系?我们先来看看 Linux 下的通配符。
===========================================
什么是通配符
通配符是一种特殊语句,主要有星号(*)和问号(?),用来模糊搜索文件。当查找文件夹时,可以使用它来代替一个或多个真正字符;当不知道真正字符或者懒得输入完整名字时,常常使用通配符代替一个或多个真正的字符。
常用正则表达式:
*
代表『 0 个或无穷多个』任意字符
?
代表『一定有一个』任意字符
[ ]
同样代表『一定有一个在括号内』的字符(非任意字符)。例如 [abcd] 代表『一定有一个字符,可能是 a, b, c, d 这四个任何一个』
[ - ]
若有减号在中括号内时,代表『在编码顺序内的所有字符』。例如 [0-9] 代表 0 到 9 之间的所有数字
[^ ]
若中括号内第一个字符为符号 (^) ,那表示『反向选择』,例如 [^abc] 代表 一定有一个字符,要是非 a, b, c 的其他字符就行。
[! ]
若中括号内第一个字符为符号 (!) ,那表示『反向选择』,例如 [!abc] 代表 一定有一个字符,要是非 a, b, c 的其他字符就行。
{String1, String2, ...}
匹配String1 或 String2 (或更多)其一字符串
{c1..c2}
匹配c1-c2 中全部字符,如 {1..2} {a..f} ,只能针对于 同一字符集的组合,
比如 {0a..0f} 会被认为是 {0a..0f} 整体为一个字符串
这种通配符在创建多个文件时比较有用
表:通配符元素优先级规则
优先级 元素 示例1 精确字符 a, \*, \\
2 字符范围 [Aa], [[:digit:]]
3 任意字符 ?
4 重复的精确字符 a+
5 重复的字符范围 [Aa]+, [[:digit:]]+
6 重复的任意字符 ?+
7 任意字符串 *
通配符使用 示例
原始目录
[root@master ~]# ll
总用量 24
-rw-r--r--. 1 root root 4 6月 21 18:09 log_01.error
-rw-r--r--. 1 root root 3 6月 21 18:37 log_02.error
-rw-r--r--. 1 root root 3 6月 21 18:33 log_0.error
-rw-r--r--. 1 root root 3 6月 21 18:34 log_a.error
-rw-------. 1 root root 575 6月 14 21:50 nohup.out
-rw-r--r--. 1 root root 10 4月 17 22:40 test.txt
示例1. 查看log开头的文件
[root@master ~]# ls log*
log_01.error log_02.error log_0.error log_a.error
示例2.查看不是以log开头的文件
先用shopt 开启 extglob模式
[root@master ~]# shopt -s extglob
[root@master ~]# ls !(log*)
nohup.out test.txt
示例3. 查看 log_0?.error 的文件的几种方式
?代表某个数字
[root@master ~]# ll
总用量 24
-rw-r--r--. 1 root root 4 6月 21 18:09 log_01.error
-rw-r--r--. 1 root root 3 6月 21 18:37 log_02.error
-rw-r--r--. 1 root root 3 6月 21 18:33 log_0.error
-rw-r--r--. 1 root root 3 6月 21 18:34 log_a.error
-rw-------. 1 root root 575 6月 14 21:50 nohup.out
-rw-r--r--. 1 root root 10 4月 17 22:40 test.txt
1)ls log_0?.error
[root@master ~]# ls log_0?.error
log_01.error log_02.error
2)ls log_0[0-9].error
[root@master ~]# ls log_0[0-9].error
log_01.error log_02.error
3)ls log_0[[:digit:]].error
[root@master ~]# ls log_0[[:digit:]].error
log_01.error log_02.error
4) ls log_0{0..9}.error
[root@master ~]# ls log_0{0..9}.error
ls: 无法访问log_00.error: 没有那个文件或目录
ls: 无法访问log_03.error: 没有那个文件或目录
ls: 无法访问log_04.error: 没有那个文件或目录
ls: 无法访问log_05.error: 没有那个文件或目录
ls: 无法访问log_06.error: 没有那个文件或目录
ls: 无法访问log_07.error: 没有那个文件或目录
ls: 无法访问log_08.error: 没有那个文件或目录
ls: 无法访问log_09.error: 没有那个文件或目录
log_01.error log_02.error
5) ls log_{01,02}.error
[root@master ~]# ls log_{01,02}.error
log_01.error log_02.error
示例4. 创建多个文件
指令 :
touch 20180622_{0..10}.log
结果 :
[root@master ~]# touch 20180622_{0..10}.log
[root@master ~]# ll总用量 24
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_0.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_10.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_1.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_2.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_3.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_4.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_5.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_6.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_7.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_8.log
-rw-r--r--. 1 root root 0 6月 22 11:36 20180622_9.log
-rw-r--r--. 1 root root 4 6月 21 18:09 log_01.error
-rw-r--r--. 1 root root 3 6月 21 18:37 log_02.error
-rw-r--r--. 1 root root 3 6月 21 18:33 log_0.error
-rw-r--r--. 1 root root 3 6月 21 18:34 log_a.error
-rw-------. 1 root root 575 6月 14 21:50 nohup.out
-rw-r--r--. 1 root root 10 4月 17 22:40 test.txt
=========================================
通配符 与 正则表达式 的区别
正则表达式用来在文件中匹配符合条件的字符串,正则是包含匹配。
grep、awk、sed等命令都支持正则表达式。
通配符用来匹配符合条件的文件名,通配符是完全匹配。
ls、find、cp这些命令不支持正则表达式,所以只能使用shell自己的通配符来进行匹配了。
首先,正则表达式是用来匹配文件中文本的字符串,而通配符是用来匹配符合条件的文件名;其次正则表达式是包含匹配,只要包含正则中的字符串,就匹配,而通配符是完全匹配,也就是说,必须要与条件中的字符串一模一样才会匹配。
===================================
基本正则表达式语法
正则表达式主要用于字符串的模式分割、匹配、查找及替换操作,下面来关注一下正则表达式基本的元字符和它的作用。
正则表达式的分类
1、基本的正则表达式(Basic Regular Expression 又叫Basic RegEx 简称BREs)
2、扩展的正则表达式(Extended Regular Expression 又叫Extended RegEx 简称EREs)
3、Perl的正则表达式(Perl Regular Expression 又叫Perl RegEx 简称PREs
元字符 | 作用 | 举例说明 |
* | 前一个字符匹配0次或者任意多次 | "a*" 匹配所有内容,包括空白行 "aa*" 匹配至少包含一个a的行 "aaa*" 匹配最后包含两个连续a的字符串 "aaaaa*"匹配最少包含4个连续a的字符串 |
. | 匹配除了换行符外的任意一个字符 | "s..d" 匹配在s和d这两个字母之间一定有两个 字符的单词 |
^ | 匹配行首 | "^hello" 匹配以hello开头的行 "^M" 匹配以大写“M”开头的行 |
$ | 匹配行尾 | "hello$" 匹配以hello结尾的行 "n$" 匹配以小写“n”结尾的行 "^$" 匹配空白行 |
[] | 匹配中括号中指定的任意一个字符,只匹配一 个字符 | "[aeiou]" 匹配任意一个元音字母, 两位字符。 "[0-9]" 匹配任意一个数字 "^[a-z]" 匹配小写字母开头的行 |
[^] | 匹配中括号的字符以外的任意一个字符 | "[^0-9]" 匹配任意一位非数字字符, "[^a-z]" 表示任意一位非小写字母 "^[^a-z]" 匹配不是小写字母开头的行 "^[^a-zA-Z]" 匹配不是字母开头的行 |
\ | 转义符。用于将特殊符号的含义取消 | "\.$" 匹配使用"."结尾的行 |
\{n\} | 表示其前面的字符恰好出现n次 | "[0-9]\{4\}" 匹配4位数字, "[1][3-8][0-9]\{9\}" 匹配手机号码 "a\{3\}" 匹配a字母连续出现3次的字符串 "[0-9]\{3\}" 匹配包含连续的3个数字的字符串 |
\{n,\} | 表示其前面的字符出现不小于n次 | "[0-9]\{2,\}" 表示两位及以上的数字。 的字符串 |
\{n,m\} | 表示其前面的字符至少出现n次,最多出现 m次 | "[a-z]\{6,8\}" 匹配6到8位的小写字母。 最多三个a |
==============================================
常用的正则表达式
参考文章:
shell 正则表达式详细整理
https://www.jb51.net/article/94354.htm
shell 编程之正则表达式
https://www.cnblogs.com/whc-uestc/p/4700360.html
数字 :
“^\d+$” //非负整数(正整数 + 0)
“^[0-9]*[1-9][0-9]*$” //正整数
“^((-\d+)|(0+))$” //非正整数(负整数 + 0)
“^-[0-9]*[1-9][0-9]*$” //负整数
“^-?\d+$” //整数
“^\d+(\.\d+)?$” //非负浮点数(正浮点数 + 0)
“^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$” //正浮点数
“^((-\d+(\.\d+)?)|(0+(\.0+)?))$” //非正浮点数(负浮点数 + 0)
“^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$” //负浮点数
“^(-?\d+)(\.\d+)?$” //浮点数
字符串:
“^[A-Za-z]+$” //由26个英文字母组成的字符串
“^[A-Z]+$” //由26个英文字母的大写组成的字符串
“^[a-z]+$” //由26个英文字母的小写组成的字符串
“^[A-Za-z0-9]+$” //由数字和26个英文字母组成的字符串
“^\w+$” //由数字、26个英文字母或者下划线组成的字符串
Email :
“^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$” //email地址
“^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$” //Email
Url :
“^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$” //url
IP :
“^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$” //IP地址
Tel :
/^((\+?[0-9]{2,4}\-[0-9]{3,4}\-)|([0-9]{3,4}\-))?([0-9]{7,8})(\-[0-9]+)?$/ //电话号码
日期校验:
/^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日 yyyy-MM-dd / yy-MM-dd 格式
"^[0-9]{4}-((0([1-9]{1}))|(1[1|2]))-(([0-2]([0-9]{1}))|(3[0|1]))$" // 年-月- 日 yyyy-MM-dd 格式
/^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
====================================
Linux Shell 脚本中正则表达式
参考文章:
shell script 在if 的判断条件正则表达式=~中引号问题
https://www.cnblogs.com/gaochsh/p/6901807.html
脚本判断 字符串与某个正则表达式 是否相等
注意:
1) 正则表达式需要写在 =~ 右侧
2) 注意用 [[ ]] 括号
#!/bin/bash date_pattern='^[0-9]{4}-((0([1-9]{1}))|(1[1|2]))-(([0-2]([0-9]{1}))|(3[0|1]))$' test_date1='2018-06-22' test_date2='2018-11-40' if [[ $test_date1 =~ $date_pattern ]] then echo "date_pattern regex math test_date1 " fi if [[ $test_date2 =~ $date_pattern ]] then echo "date_pattern regex math test_date2 " fi if [[ $date_pattern =~ $test_date1 ]] then echo "date_pattern regex math test_date2, revert!! " fi
[root@master ~]# sh data_regex.sh
date_pattern regex math test_date1