正则表达式

Posted burnovblog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了正则表达式相关的知识,希望对你有一定的参考价值。

  在Linux shell脚本中,使用sed gawk命令的关键就是自如的使用正则表达式;我们需要准确的匹配数据流量;

1、正则表达式是什么

  1.1、正则表达式的定义

    正则表达式,是我们在Linux系统下,过滤数据的模式模板。只有先匹配到流量或者数据,我们才能采用对应的操作;

    在之前我们又通过文件统配符来列出问价的例子:ls -al da*

    这则表达式和通配符工作方式相似,但是要比通配符复杂的多;

  1.2、正则表达式的类型

    不同的语言使用不同的正则表达式类型;不同类型我叫做不同模式的正则表达式,它是通过正则表达式引擎实现的。

    正则表达式引擎分类:1、POSIX基本正则表达式(BRE)引擎;2、POSIX扩展正则表达式(BRE)引擎;

    我们这里只讨论sed和gawk所能够支持的正则表达式;

2、定义BRE模式

  基本的BRE模式是匹配数据流中文本字符。

  2.1、纯文本

    打印匹配上的文本

$ echo "This is a test" | sed -n /test/p
This is a test
$ echo "This is a test" | sed -n /trial/p
$
$ echo "This is a test" | gawk /test/{print $0}
This is a test
$ echo "This is a test" | gawk /trial/{print $0}‘  # $0表示整行内容
$

    sed和gawk都区分大小写

$ echo "This is a test" | sed -n /this/p
$
$ echo "This is a test" | sed -n /This/p
This is a test
$

    不必局限于单词是否写全

$ echo "The books are expensive" | sed -n /book/p
This books are expensive

    空格字符也能识别

$ echo "This is line number 1" | sed -n /ber 1/p
This is line number 1

  2.2、特殊字符

    有几个特殊的字符,用来匹配文本: . * [] ^ $ {} \\ + ? | ()

    转义字符: \\ : 恢复原有字符的意思

sed -n /\\$/p data2  #恢复 $ 符号原有的意思

    反斜杠对于反斜杠自己也要进行转意

echo "\\ is a special character" | sed -n \\//\\p

    虽让在正斜杠不是特殊字符,但是在sed和gawk中依然需要反斜杠转意

echo "3 / 2" | sed -n /\\//p

  2.3、定位符

    1、从头开始

    托字符 ^ 定义文本开头内容

echo "This book store" | sed -n /^book/p
echo "Books are great" | sed -n ‘/^Books/p

    托字符由换行符决定,且区分大小写的;

    如果托字符,不放在文本开始位置,那就是普通字符,不再充当特殊字符;

echo "This ^ is a test" | sed -n /s ^/p

    2、查找结尾

    $ 符定义结尾

echo "This is a good book" | sed -n /book$/p 

    3、联合定位

    以this is a test开头,同时以this is a tes结尾

$ sed -n /^this is a test$/p data4
this is a test

    第二种情况 ^$ 可以表示空白行

  2.4、点字符

    点字符(.) 用于匹配除了换行符之外的任意单个字符;

$ sed -n /.at/p data6
The cat is sleeping.

  2.5、字符类

    [] 中括号指定一类字符,例如 [abc] 配置abc中任意一个字符;

$ sed -n /[ch]at/p data6
The cat is sleeping.
That is a very nice hat.

    只有 at 前面没有 c或者h 上面的字符串也是无法匹配到的;

    常用方式:

$ echo "Yes" | sed -n /[Yy][Ee][Ss]/p
$ echo "yEs" | sed -n ‘/[Yy][Ee][Ss]/p

    匹配邮政编码数字

$ sed -n > /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p
>  data8  #匹配了只有五位的任意数字串

    接收常见的错误单词拼写

$ sed -n > /maint[ea]n[ae]nce/p
> /sep[ea]r[ea]te/p
>  data9

  2.6、否定字符类

    在范围内使用托字符,表示否定,例如: [^ch] 出去ch外的所有字符

$ sed -n /[^ch]at/p data6

  2.7、使用范围

    短划线符号可以表示在字符中使用一些列字符范围。[0-9]:表示 0123456789中的任意数字;

$ sed -n /^[0-9][0-9][0-9][0-9][0-9]$/p data8

    同样的方式也适用于字母

$ sed -n /[a-ch-m]at/p data6  #从a到c,从h到m,之间的匹配字符串 abc higklm 这两组字符串的组合;

  2.8、特殊字符类

    BRE包含一些特殊字符:

技术图片

技术图片

    这些特殊字符,直接使用即可;

  2.9、星号

    星号(*),表示星号前一个字符出现多次 i*:表示iiiii...出现零次多次;

技术图片

    也可以指定任意组合出现多吃

技术图片

3、扩展的正则表达式

  gawk比sed更加灵活,它能够识别ERE模式的正则表达式,也就是扩展的正则表达式;

  3.1、问号

    ? 表示前面的字符出现零次或一次。但是 * 号表示零次或多次;

$ echo "bt" | gawk /be?t/{print $0}
bt
$ echo "beet" | gawk /be?t/{print $0}
$

    ? 也可以和字符串连用

$ echo "bt" | gwak /b[ae]?t/{print $0}
"bot" "bat" "bet" "beat" "beet" "baet"

  3.2、加号

    + 与 ? 正好相反,表示前面的字符出现一次和多次;

$ echo "beeet" | gawk /be+t/{print $0}
"beet" "bet" "bt"

    也可以与字符串连用

$ echo "bt" | gawk /b[ea]+t/{print $0}
"bat" "bet" "beat" "beeeat"

  3.3、使用大括号

    指定可重复的次数{m}:正好出现m次;{m,n}:最少出现m此,最多出现n次;

$ echo "bet" | gawk --re-interval /be{1}t/{print $0}
"bt" "beet"

    字符出现的范围

$ echo "bt" | gawk --re-interval /be{1,2}t/{print $0}
"bet" "beet" "beeet"

    也可以结合字符串来实现匹配

$ echo "bt" | gawk --re-interval /b[ea]{1,2}t/{print $0}‘ #e和a出现的总次数不能多于两次
"bt" "bat" "bet" "beat" "beet" "beeat" "baeet" "beaaet"

  3.4、管道符号

    这里的管道符表示或者OR

$ echo "This cat is asleep" | gawk /cat|dog/{print $0}
$ echo "He has a hat." | gawk ‘/[ch]at|dog/{print $0}‘

  3.5、将表达式分组

    圆括号,可以将正则表示是进行分组;一个括号内的字符串,作为一个字符进行处理;

$ echo "Saturday" | gawk /Sat(urday)?/{print $0}
Saturday

    分组可以结合管道符使用

$ echo "cat" | gawk /(a|b)a(b|t)/{print $0}

4、正则表达式实战

  4.1、计算目录文件

    统计PATH环境变量中的可执行文件数量。

#!/bin/bash
# count number of files in your PATH
mypath=`echo $PATH | sed s/:/ /g`
count=0
for directory in $mypath
do
    check=`ls $directory`
    for item in $check
    do
        count=$[ $count + 1 ]
    done
    echo "$directory - $count"
    count=0
done

  4.2、验证电话号码

    常见电话号码类型:(123)456-7890  (123) 456-7890  123-456-7890  123.456.7890

    ^\\(?   括号可能有,也可能没有

    [2-9][0-9]{2}  美国点好以2开头,只要指定后面的电话就可以了

    \\)?  反括号,有可能有,也可能没有

    (| |-|\\.)  指定这个位置,可能是没有字符,也可能是空格,也可能是 - ,也可能是 .

    [0-9]{3}  3为0-9任意字符

    ( |-|\\.)  指定空格,-,. 中的任意一个字符

    [0-9]{4}$  以四组任意数字结尾;

    记住:在gawk程序中使用正则表达式间隔时,必须使用--re-interval命令行选项。

#!/bin/bash
# script to filter out bad phone numbers
gawk --re-interval /^\\(?[2-9][0-9]{2}\\)?(| |-|\\.)[0-9]{3}( |-|\\.)[0-9]{4}/{print $0}
cat phonelist | ./isphone  #过滤掉phonelist文件中的非电话号码

  4.3、解析电子邮件地址

    [email protected]

    username:包括圆点,短划线,加好,下划线

    hostname:包括圆点,下划线

    ^([a-zA-Z0-9_\\-\\.\\+]+)@  #用户名

    ([a-zA-Z0-9_\\-\\.]+)  #这个模式可以匹配的文本,server或者server.subdomain或者server.subdomain.subdomain

    \\.([a-zA-Z]{2,5})$  #顶级域名的表达方式

    组合起来

^([a-zA-Z0-9_\\-\\.\\+]+)@([a-zA-Z0-9_\\-\\.]+)\\.([a-zA-Z]{2,5})$
$ echo "rich$here.now" | ./isemail

 

以上是关于正则表达式的主要内容,如果未能解决你的问题,请参考以下文章

markdown 正则表达式模式片段

正则表达式匹配特定的 URL 片段而不是所有其他 URL 可能性

循环通过 python 正则表达式匹配

asp.net 使用正则表达式验证包含打开/关闭括号片段的属性字符串

攻破难啃的骨头-正则表达式(转)

正则表达式的贪婪和非贪婪模式