Linux_Shell_Shell 中的正则表达式 与 常用正则表达式


在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这两个字母之间一定有两个

字符的单词
"s.*d" 匹配在s和d字母之间有任意字符
".*" 匹配所有内容

^ 匹配行首 "^hello" 匹配以hello开头的行
"^M" 匹配以大写“M”开头的行
$ 匹配行尾 "hello$" 匹配以hello结尾的行 
"n$" 匹配以小写“n”结尾的行
"^$" 匹配空白行
[] 匹配中括号中指定的任意一个字符,只匹配一
个字符

"[aeiou]" 匹配任意一个元音字母,
"[0-9]" 匹配任意一位数字,
"[a-z][0-9]" 匹配小写字母和一位数字构成的

两位字符。
"s[ao]id" 匹配s和i字母中,要么是a,要么是o

"[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,\}" 表示两位及以上的数字。
"[0-9]\{3,\}[a-z]" 匹配最少用连续3个数字开头

的字符串

\{n,m\} 表示其前面的字符至少出现n次,最多出现
m次

"[a-z]\{6,8\}" 匹配6到8位的小写字母。
"sa\{1,3\}i" 匹配在字母s和i直接有最少一个a,

最多三个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 




猜你喜欢

转载自blog.csdn.net/u010003835/article/details/80763526