正则表达式

正则表达式

正则表达式是一种匹配模式,通过正则表达式,用户可以精准匹配自己想要的内容。

正则表达式基本是由2个部分组成,分别是一般字符及特殊字符。一般字符是指没有任何意义的字符,也就是说字符没有特殊含义,比如,a,b,c,d等字符;特殊字符是指拥有特殊含义,并且在一定情况下可以转为一般字符那种,也被称为元字符。

正则表达式可以分为基础正则表达式(BRE)扩展正则表达式(ERE)。

  • 基础正则表达式
  • 常见的特殊字符:
BRE/ERE

特别字符

描述(默认以BRE功能为主)

2

$

匹配输入字符串的结尾位置。要匹配$ 字符本身,ERE可以放在任意位置

BRE

( )

标记一个子表达式的开始和结束位置。要匹配这些字符,请使用\( 和\)

2

*

匹配前面的子表达式零次或多次。要匹配* 字符,请使用\*(位于第一个字符就没有任何意义,)

2

+

匹配前面的子表达式一次或多次。要匹配+ 字符,请使用\+

2

.

匹配除换行符\n 之外的任何单字符。要匹配. ,请使用\. ;nul除外

 

[

标记一个中括号表达式的开始。要匹配[,请使用\[

2

?

匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配? 字符,请使用\?

 

\

将下一个字符标记为或特殊字符、或原义字符、或向后引用、或八进制转义符。例如,'n' 匹配字符'n'。'\n' 匹配换行符。序列'\\' 匹配"\",而'\(' 则匹配"("

2

^

匹配输入字符串的开始位置,除非在方括号表达式中使用,此时它表示不接受该字符集合。要匹配^ 字符本身,请使用\^;ERE置于任何位置都有意义

 

{

标记限定符表达式的开始。要匹配{,请使用\{

2[...]方括号表达式,匹配方括号内的任一字符, [a-c],连字符,指的是范围,[^a],^放在方括号里面,则是取反的意思,不匹配里面任一字符
BRE\{n,m\}

区间表达式,匹配它前面单个字符重现的次数。\{n\}指重现n次, \{n,\}至少重现n次,\{n,m\}重现n到m次 ,n与m的值介于0到RE_DUP_MAX之间,centos7中,最大值是32767

# getconf RE_DUP_MAX
32767

BRE \( \)\( "保留空间"\) 主要是存储子表达式,最多可以存储9个
ERE{n,m}是属于ERE独有的区间表达式
2

|

指明两项之间的一个选择。要匹配|,请使用\|   如:Y | y

 

定位符

 
 

^

匹配输入字符串开始的位置

 

$

匹配输入字符串结尾的位置

 

非打印字符

 
BRE

\s

空格 \s*0个或者多个空格
 

\n

匹配一个换行符

 

\r

匹配一个回车符

 

\t

匹配一个制表符
  • 常见表达式:

# cat wc.sh

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "touch"       #只打印"touch"几个字符,跟常规grep匹配差不多

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "^ma"     #匹配以"ma"字符开头的行

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "mysql$"  #匹配以"mysql"字符结尾的字符,跟命令行中的$差不多

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "^matchtouchmkdirnginxmysql$"  #匹配完整的内容,也就是这一行只能且只有这些内容

matchtouchmkdirnginxmysql 

# cat wc.sh | egrep "[nN]ginx"  #[ ]里面是匹配单个字符,只要满足这个要求,无论是啥字符都行,同时在很多命令中,[ ]里面的内容是可选的

matchtouchmkdirnginxmysql 

# cat wc.sh | egrep "c.m"     #匹配c-m之间的单个字符

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "c.*m"  #匹配c-m之间的0个或者多个字符

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "c.+m" # + 是匹配前面子表达式的1个或者多个字符

matchtouchmkdirnginxmysql

# cat wc.sh | egrep "c.?m"    # ? 匹配前面0个或者1个字符

matchtouchmkdirnginxmysql

  • 常见特殊字符集(在shell里面实践了一下好像跑不了,据说是php的正则表达一种):

  • 基础正则表达式

支持单个字符匹配及多个字符匹配 (用到的字符就是BRE里面的所有标准字符及特殊字符)

[ : : ] 字符集,可以把多个字符组合起来成为一个完整的字符串

[ . . ] 排序元素 主要是进行排序

[ = ] 等价字符集,也就2边的字符都是相等的

这几种字符集方式的实现都需要[ ] 来帮忙实现。

在 [ ] 中所有字符都会失去其特殊含义。[ * \ . ] 就是字面上的意思,正确写法:[ ] * \ .]

  • 分组

分组简单来说是把一串字符串,通过 \( \) 方式形成一个子表达式(单个字符),供后面的正则去匹配,并且最多存储9个子表达式,用数字1-9表示。1个 \( \) 就是一个分组,就是一个整体。

$ cat  ac.txt
hello
helloo
hellooo
hellohel
hellohell
hellohello  

$ cat  ac.txt | grep "hello\{3\}"  #\{n\}在BRE里面是匹配前面单个字符出现的次数
hellooo

$ cat  ac.txt | grep "\(hello\)\{2\}"  
hellohello

#在上面的表里面,有个 \( \) 特殊字符,这里面主要是存放子表达式的,也就是把内容整合为一个整体,
供后面的正则去匹配,简单来说就是把多个字符组合一起,成为单个字符

分组还可以嵌套的:
$ cat  ac.txt  | tail -3
hellohello
queuequeue
queue
$ cat  ac.txt  | grep '\(q\(ue\)\{2\}\)\{2\}'
queuequeue
#这就是个简单的嵌套,也就是这样:\( \( \) \)优先运行里面的\( \) 然后在运行外面最大的\( \)
上面例子解析:
首先运行 q\(ue\)\{2\} 结果是queue,也就是把ue作为一个整体匹配了出现的次数也就是2次
然后运行最外面的 \(queue\)\{2\},结果就是queuequeue,在进行子表达式嵌套的时候会把最里面子
表达的结果给外面的子表达式作为结果输入,跟Linux中的|一个意思。

grep '\(ue\)\{2\}\)' 与 grep '\(ue\{2\}\)' 是有区别的,前者是把ue作为一个字符,后者是把e作为字符
$ cat ac.txt | grep '\(ue\)\{2\}'
queue
$ cat ac.txt | grep '\(ue\{2\}\)'
quee


  • 后向引用
$ cat 7.txt
tzc 	word yunying
lij 	word lij
haibing word yunying


需求1:打印tzc那一行
$ cat 7.txt | grep 't.\{2\}\s*word y.\{3,8\}' # . 是表示除\n之外的任意单个字符,这个表示只匹配tzc了
tzc 	word yunying

需求2:匹配word字段周边都相同的行
$ cat 7.txt | grep '\(l.\{2\}\)\s*word \1'  #出现全新玩法 \1
lij 	word lij
注:\1是什么了?这个就是后向引用,也就是\1是引用第一个分组的结果,\( \)这就是分组括号,里面的结果就是分组结果,\1就是匹配第一个分组的结果。
严重强调:\1 \2等等只能匹配\( \)的结果

$ cat  test.txt

abccccabeeee word abccccabeeee

$ cat  test.txt | grep '\(\(abcc.\{2\}\)\ab.\{4\}\) word \2'

abccccabeeee word abccccabeeee

$ cat  test.txt | grep '\(\(abcc.\{2\}\)\ab.\{4\}\) word \1'

abccccabeeee word abccccabeeee

根据上面结果显示,后向引用顺序是由左侧分组符号进行排序的也就是 ((( 分别是\1 \2 \3

后向引用需要以分组为前提的不然就引用不了,后向引用只能引用分组符号 \( \)的匹配结果

\1 表示引用第一个分组括号里面的正则匹配结果,\2 \3依次类推

  • 优先级

    BRE运算符优先级,由高至低

运算符表示含义
[..] [==] [::]用于字符排序的方括号符号
\metacharacter转义的 meta 字符
[ ]方括号表达式
\( \)   \digit 子表达式与后向引用
*\{   \}前置单个字符重现的正则表达式
无符号(no symbol)连续
^  $锚点
  • 扩展正则表达式

ERE是扩展正则表达式,扩展正则表达式在标准正则表达式上新增一些功能,能满足大家的工作需求。

单个字符匹配跟跟BRE方法是差不多的,但是ERE中的awk里面 \ 有特殊的含义。

  • 反向应用:在通过sed进行扩展正则的时候一样可以使用
  • 字符匹配:ERE在字符匹配方面,与BRE有明显的不同,其中*的功能是一样的。
  • 区间表达式:ERE也存在区间表达式,但是不在是 \{ \},而是以 { } 这种形式展现,且不需要前置 \ 字符。
  • 分组:ERE进行分组的话是 ( ),不需要在加 \ 字符
  • 交替: | 跟BRE方式一样,二选一那种  (read|write) 还有是添加锚点符那种 ^action|active$ 匹配字符串开始处是否有action或者结尾处是否有active     ^(ac|bc)$匹配当前内容里面是否有ac或者bc字符串
  • 优先级:跟BRE是一样的由高到低

  • 额外正则运算表达符

运算符表示含义
\w匹配任意单词(可以是单个字符,字符串等等) ac bh ki js n r
\W匹配任意符号(可以是单个,也可以是多个) ? \ + - == [ ] { } -- ()
\< \>\<ac 匹配以ac开头的字符 df\> 匹配以df结尾的字符  \<qwe\> 那就只匹配qwe字符
\b

单词边界,就是单词和符号之间的边界,单词就是\w匹配的内容,符号是\W匹配的内容,也就是匹配字跟空格之间的一个位置

# cat wc.sh
matCHtouc1223mysl
ac bhmore ki js
jkless

# cat wc.sh  | egrep 's\b'
ac bhmore ki js
jkless

# cat wc.sh  | egrep '\bma'
matCHtouc1223mysl

# cat wc.sh  | egrep '\bac\b'
ac bhmore ki js

总结:通过\b可以匹配开头处的内容及结尾处的内容,至于中间的内容需要\B来匹配

注:更深层次的理解,等我理解完毕再来补充

\B

非单词边界,是单词与单词,符号与符号之间的边界

# cat wc.sh  | egrep '\B1223\B'
matCHtouc1223mysl
# cat wc.sh  | egrep '\B1223'
matCHtouc1223mysl
# cat wc.sh  | egrep '1223\B'
matCHtouc1223mysl

总结:简单来说就是匹配某个内容是否存在

注:更深层次的理解,等我理解完毕再来补充

非常好的正则使用例子:
root@test:/opt/scripts 12:47:52
$ cat hl-ip.txt.bak | sort | awk -F'/' '{print $3,$0}' | sed -r 's/.*\.(\w+).(com|net) /\1.\2 /'| sort -k 1 | awk '{print $2}'
http://10.pic.123456.com/2017-08/mB8CBuXo8u87MFthMmWSEJymrQHS2G5hkgWSAR2q.jpeg
http://1.pic.234567.com/2017-07/FLeGYVYY5EPakINvcORvJvxoR9z19HG2McSuAeww.jpeg

 


位置参数

位置参数分别是$0 $1 $2.....$n

# sh system.sh 1 2 3 4

根据上面那个命令展示:$0 就是命令本身 1 是$1 2 是$2 3是$3 依次类推


程序跟踪测试

在Linux命令行:sh -x 叫脚本  #一般都是使用这种方式

在shell脚本里面:以set -x开启跟踪模式  以set -x关闭跟踪模式,例如:

#!/bin/bash
who | wc -l >/dev/null
set -x
if [ $? = 0 ]
then
   echo "zhixingchenggong"
else
   echo "zhixingfailed"
fi
set -x
echo abc

root@test:/opt/scripts/my.scripts 18:52:22
# sh wc.sh
+ '[' 0 = 0 ']'
+ echo zhixingchenggong
zhixingchenggong
+ set -x
+ echo abc
abc

特殊文件

/dev/null 和 /dev/tty

/dev/null 熟称黑洞,将标准输出输出到这个文件后,输出结果会被系统给丢掉,不占用系统任何空间,非常的实用。

/dev/tty  当程序打开此文件时,shell会自动将它重定向到一个实体终端(不怎么用过)


文本输出

echo

printf

printf是模仿C程序库的printf()库里程序,但是功能相当于与echo而言,更复杂,更灵活。printf不支持自动换行,echo支持自动换行

root@test:/opt/scripts/my.scripts 17:45:12
# printf "hello word"
hello wordroot@test:/opt/scripts/my.scripts 17:45:37
# echo "hello word"
hello word
root@test:/opt/scripts/my.scripts 17:47:38
# printf "hello word\n"
hello word
注:根据上图所示,printf不支持换行,需要加\n才行

用法:printf FORMAT [ARGUMENT]...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值