正则表达式

     正则表达式是处理字符串的一种表示方式,需要额外的支持工具来辅助在这里我们使用grep。另外,不同的语系对正则表达式的输出会有不同的影响效果。举例来说,在英文大小写的编码顺序中,zh_CN.big5 与 C 两种语系的输出结果分别如下:

LANG = C 时: 0 1 2 3 4 ...  A B C D ... Z a b c d ... z
LANG = zh_CN 时: 0 1 2 3 4 ... a A b B c C d D ... z Z

 

因此,在使用正则表达式时,要特别留意当时环境与语系,否则就会发现与别人不相同的选取结果。

 

     在这里,我们使用的是兼容POSIX标准,因此使用C语系,下面列出一部分常用的特殊符号:

[:alnum:]            代表英文大小写字符及数字,即0-9,A-Z,a-z
[:alpha:]             代表任何英文大小写字符,即A-Z,a-z
[:blank:]             代表空格键与[Tab]按键
[:cntrl:]              代表键盘上的控制按键,即包括CR, LF, Tab, Del等
[:digit:]              代表数字
[:graph:]            除了空格键(空格键与[Tab]按键)之外的其他按键
[:lower:]             代表小写字符
[:print:]              代表任何可以被打印出来的字符
[:punct:]             代表标点符号(punctuation symbol),即" ' ? ! ; . , # $
[:upper:]             代表大写字符
[space::]             任何会产生空白的字符
[:xdigit:]             代表十六进制的数字类型,因此包括0-9, A-F, a-f的数字与字符

 

其中常用的有[:alnum:], [:alpha:], [:upper:], [:lower:], [:digit:]等,要牢记~!

 

    grep的一些高级参数。grep是一个很常见也很常用的命令,最重要的功能就是进行字符串额对比,然后将符合用户要求的字符串打印出来。需要说明的是grep在数据中查找一个字符串时,是以整行为单位来进行数据的选取的。

$ grep [-A] [-B] [--color=auto] '搜寻字符串' filename
参数:
-A: 后面可加数字,为after的意思,指除了列出该行外,后续的n行也列出来;
-B: 后面可加数字,为before的意思,指除了列出该行外,前面的n行也列出来;
--color=auto  可将正确选取的那个数据列出颜色

范例:
1)用dmesg列出内核信息,再议grep找出内含eth的那行
$ dmesg | grep 'eth'

2) 承上,将找到的关键字显色,且加上行号来显示
$ dmesg | grep -n --color= auto 'eth'

3) 承上,在关键字所在行的前两行和后三行也显示出来
$ dmesg | grep -n -A3 -B2 --color=auto 'eth'

 

 

    为了简化下面的使用,用alias命令使grep表示grep --color=auto,命令如下: alias grep='grep --color=auto'.   下面进行基础正则表达式的练习。我们使用的是样例来自:http://linux.vbird.org/linux_basic/0330regularex/regular_express.txt 

查找特定字符串

  • $ grep -n 'the' regular.txt
    结果显示如下:
    12:I can't finish the test.
    16:the symbol '*' is represented as start.
    19:You are the best is mean you are the no. 1.
    20:The world <Happy> is the same with "glad".
    22:google is the best tools for search keyword.
    
    若想反向选择?当该行没有'the'字符串时才会显示在屏幕上。那么,使用:
    $ grep -vn 'the' regular.txt
    
    若想要取得不论大小写的‘the’字符串,使用如下命令:
    $ grep -in 'the' regular.txt
    结果显示如下:
    12:I can't finish the test.
    13:Oh! The soup taste good.
    16:the symbol '*' is represented as start.
    18:The gd software is a library for drafting programs.
    19:You are the best is mean you are no. 1.
    20:The world <Happy> is the same with "glad".
    22:google is the best tools for search keyword.
  • 利用中括号[]来查找集合字符
  • 若想查找test或taste这两个单词,可以发现他们有共同的 't?st'存在,因此我们可以这样查找:
    $ grep -n 't[ea]st' regular.txt
    结果显示如下:
    1:This file is a test file.
    12:I can't finish the test.
    13:Oh! The soup taste good.
    
    其实不管[]里面有几个字符,它都只代表一个字符。又如,想查找有 oo 的字符串时,使用:
    $ grep -n 'oo' regular.txt
    结果显示如下:
    5:"Open Source" is a good mechanism to develop programs.
    6:apple is my favorite food.
    7:Football game is not use feet only.
    13:Oh! The soup taste good.
    22:google is the best tools for search keyword.
    23:goooooogle yes!
    
    但是,如果不想要 oo 前面有 g 的话的?此时,可以利用集合字符的反向选择 [^] 实现:
    $ grep -n '[^g]oo' regular.txt
    结果显示如下:
    6:apple is my favorite food.
    7:Football game is not use feet only.
    22:google is the best tools for search keyword.
    23:goooooogle yes!
    
    注意,第23行也显示出来,是因为go(oooo)ogle,可以认为前后都是o,因此也显示出来了。再来,假设我们oo前面不想有小写字符,我们可以这样写[^abcd...z]oo,但这样似乎太不方便,而由于小写字符的ASCII码是连续的,因此我们可以这样简化:
    $ grep -n '[^a-z]00' regular.txt
    结果显示如下:
    7:Football game is not use feet only.
    
    也就是说,如果我们所选取的字符串是连续的,如大写英文/小写英文/数字时,就可以使用[a-z], [A-Z], [0-9]. 同样地,如果我们的要求字符串是数字或英文呢?就可以将它们全部写在一起 [a-zA-Z0-9].
    $ grep -n '[0-9]' regular.txt
    
    考虑到语系对于编码顺序的影响,连续编码除了使用‘-’外,还可以使用我们前面介绍的特殊字符。
    $ grep -n '[^[:lower:]]oo' regular.txt
    结果显示如下:
    4:I am going to my home.
    5:"Open Source" is a good mechanism to develop programs.
    6:apple is my favorite food.
    7:Football game is not use feet only.
    8:this dress doesn't fit me.
    9:However, this dress is about $ 3183 dollars.
        .
    .
    . 24:go! go! Let's go. 25:# I am VBird
  •  行首与行尾字符^$

  • 在上面的例子中,我们得到了包含"the"的字符,但是如果想让the只出现在行首位置呢?这个时候就应该使用制表符了。使用如下命令:
    $ grep -n '^the' regular.txt
    结果显示如下:
    16:the symbol '*' is represented as start.
    
    如果我们想要结果开头是小写的那一行出列呢?使用如下命令:
    $ grep -n '^[a-z]' regular.txt / $grep -n '^[[:lower:]]' regular.txt
    结果显示如下:
    2:vi is a little difficult.
    6:apple is my favorite food.
    8:this dress doesn't fit me.
    14:motorcycle is cheap than car.
    16:the symbol '*' is represented as start.
    22:google is the best tools for search keyword.
    23:goooooogle yes!
    24:go! go! Let's go.
    
    如果不想要开头是英文字母,可以这样写:
    $ grep -n '^[a-zA-Z]' regular.txt / $grep -n '^[^[:alpha:]]' regular.txt
    结果显示如下:
    5:"Open Source" is a good mechanism to develop programs.
    25:# I am VBird
    
    注意:通过上面的例子我们可以看出,^符号在[]里面与在[]外面是不同的!!!![^...]
    是指我们得到的结果中不包含中括号[]的字符(反向选择);而^[]是指定位在行首,表示行首制表符。
    
    如果我们想得到行尾结束为小数点"."的那一行,该如何处理?
    $ grep -n '\.$' regular.txt
    结果显示如下:
    4:I am going to my home.
    5:"Open Source" is a good mechanism to develop programs.
    6:apple is my favorite food.
          .
    .
    .
    19:You are the best is mean you are the no. 1. 20:The world <Happy> is the same with "glad". 21:I like dog. 22:google is the best tools for search keyword. 24:go! go! Let's go. 特别的是,小数点"."具有其他的意义,因此我们使用转移字符"\"来加以解除其特殊意义. 如果我们想找出哪一行是“空白行”该怎么表示?也就是说该行没有任何输入数据,可以使用如下语句: $ grep -n '^$' regular.txt 解析:因为只有行首跟行尾,因此使用上面的语句就可以找出空白行。
    假设你已经知道一个程序脚本(shell script)或者是配置文件中,空白行与#开头的那一行是批注,因此如果你要将数据列出来给别人参考时,可以将这些数据省略掉方便观察,那么该如何实现?看下面这个例子。 $
    cat -n /etc/syslog.conf 列出syslog.conf的所有数据显示如下: 1 # Note that flat file logs are now configured in /etc/asl.conf 2 3 install.* @127.0.0.1:32376 用如下命令省略其中的空白行和注释行: $ grep -v '^$' /etc/syslog.conf | grep -v '^#' 结果显示如下: install.* @127.0.0.1:32376
  • 任意一个字符.与重复字符*
    • 在bash中,我们知道通配符*可以用来表示任意字符(0个或者多个),但是正则表达式并不是通配符~!两者是不同的~!在正则表达式中,"."表示绝对有一个任意字符的意思!这两个字符在正则表达式中的意义如下:
    • .(小数点):表示一定有一个任意字符的意思;
    • *(星号):表示重复前一个0到无穷多次的意思,为组合形态。
    • 比如我们想要找出g??d的字符串,即共有四个字符,开头是g,而结尾是d,可以使用下面的语句:
      $ grep -n 'g..d' regular.txt
      结果显示如下:
      5:"Open Source" is a good mechanism to develop programs.
      13:Oh! The soup taste good.
      20:The world <Happy> is the same with "glad".
      $ grep -n 'o*' regular.txt
      结果显示如下:
      列出了文件中所有的数据。(原因是*表示重复前面的字符0次或无穷多次,因此有可能重复0次,把所有的数据都打印出来)
      
      $ grep -n 'oo*' regular.txt
      结果显示如下:
      将所有只要包含一个o的数据都列出来了。(原因同上。oo*只会保证第一个o一定会出现,因此是哟啊包含一个o的数据都会被列出来)
      
      $ grep -n 'ooo*' regular.txt
      结果显示如下:
      5:"Open Source" is a good mechanism to develop programs.
      6:apple is my favorite food.
      7:Football game is not use feet only.
      13:Oh! The soup taste good.
      23:google is the best tools for search keyword.
      24:goooooogle yes!
      这种情况下才会列出我们想要的数据。(原因是只有前两个oo能够保证显示出来,后面还会跟着0个或者多个o)
    • 练习:如果我们想要字符串开头与结尾都是g,但是两个g之间仅能存在至少一个o,即g0g, goog, gooooog等,则应使用如下语句:
      $ grep -n 'goo*g' regular.txt
      结果显示如下:
      24:goooooogle yes!
      
      如果我们想找出g开头与g结尾的字符串,中间的字符可有可无,那该如何写?
      $ grep -n 'g*g' regular.txt
      结果显示如下:
      4:I am going to my home.
      5:"Open Source" is a good mechanism to develop programs.
      7:Football game is not use feet only.
      13:Oh! The soup taste good.
      17:Oh!    My god!
      18:The gd software is a library for drafting programs.
      20:The world <Happy> is the same with "glad".
      21:I like dog.
      23:google is the best tools for search keyword.
      24:goooooogle yes!
      25:go! go! Let's go.
      
      如果我们想得到g...g的字符串该如何写表达式呢?使用如下语句:
      $ grep -n 'g.*g' regular.txt
      结果显示如下:
      4:I am going to my home.
      5:"Open Source" is a good mechanism to develop programs.
      18:The gd software is a library for drafting programs.
      23:google is the best tools for search keyword.
      24:goooooogle yes!
      25:go! go! Let's go.
      
      下面,如果我们想得到找出“任意数字”的行列呢?
      $ grep -n '[0-9][0-9]*' regular.txt / $ grep -n '[[:digit:]][[:digit:]]*' regular.txt
      结果显示如下:
      9:However, this dress is about $ 3183 dollars.
      19:You are the best is mean you are the no. 1.

 

 

 

  • 规定连续RE字符范围{}.
    • 在上面,我们可以利用.和*来设置0到无穷多个重复字符,那如果我们想要限制一个范围区间内的重复字符呢?比如,我们想得到2~5个o的连续字符串该如何做?此时就应该用到限定范围的字符{}了.但是因为{与}的符号在shell是由特殊意义的,因此,我们必须要使用转义字符\使它失去特殊意义才行。至于{}的语法是这样的,假设我要找两个o的字符串,可以是:
    • $ grep -n 'o\{2\}' regular.txt
      结果显示如下:
      5:"Open Source" is a good mechanism to develop programs.
      6:apple is my favorite food.
      7:Football game is not use feet only.
      13:Oh! The soup taste good.
      23:google is the best tools for search keyword.
      24:goooooogle yes!

       

    • 假设我们要找g后面接2到5个o,然后再接一个g的字符串,应该这样写:
    • $ grep -n 'go\{2,5\}g' reguar.txt
      结果显示如下:
      23:google is the best tools for search keyword.

       

    • 如果我们想要的是2个o以上的gooo..og呢?
    • $grep -n 'gooo*g' regular.txt / $ grep -n 'go\{2,\}g' regular.txt
      结果显示为:
      23:google is the best tools for search keyword.
      24:goooooogle yes!

 

    总结,基础正则表达式字符(characters)

^word   

意义:待查找的字符串在行首。

例:查找#为开头的那一行,并列出行号

grep -n '^#' regular.txt

word$

意义:待查找的字符串在行尾。

例:将行尾为!的那一行打印出来

grep -n '!$' regular.txt

.

意义:代表一定有一个任意字符的字符

例:查找的字符串可以是(eve) (eae) (eee) (e e),但不能仅有(ee)! 即e与e之间“一定”仅有一个字符,空格也属于一个字符。

grep -n 'e.e' regular.txt

\

意义:转义字符,将特殊符号的特殊意义去除

例:查找含有单引号'的那一行

grep -n '\'' regular.txt 

*

意义:重复零个到无穷多个的前一个字符。

例:找出含有(es) (ess) (esss)等得字符串,注意,因为*可以是0个,所以es也是符合条件带查找字符串。另外,因为*为重复前一个RE字符,因此,在*之前必须紧挨着一个RE字符!例如任意字符则为“.*”

grep -n 'ess*' regular.txt

[list]

意义:从字符集合的RE字符里面找出想要选取的字符

例:查找含有(gl)或(gd)的那一行。注意:在[]中代表一个待查找的字符。如"a[afl]y"代表待查找的字符串可以是aay, afy, aly,即[afl]代表a或f或l的意思

grep -n 'g[ld]' regular.txt

[n1-n2] 

意义:从字符集合的RE字符里面找出想要选取的字符范围

例:查找含有任意数字的那一行。需要留意的是,[]中的减号-是由特殊含义的,它代表两个字符之间的所有连续字符。但这个连续与否与ASCII编码有关。

grep -n '[0-9]' regular.txt

[^list]

意义:从字符集合的RE字符里面找出不要的字符串或者范围

例:查找的字符串可以是(oog) (ood) 但不能是(oot). ^在[]里表示的意义是“反向选择”.例如我不要大写字符,则应写为[^A-Z]. 需要注意的是,若写为grep -n '[^A-Z]', 会发现文件内所有的行都被列出,因为[^A-Z]表示的是“非大写字符”,每一行中都有小写字符。

grep -n 'oo[^t]' regular.txt

\{n.m\}

意义:连续n到m得前一个RE字符,若为\{n\}则是连续n个的前一个RE字符,若为\{n,\}则是连续n个以上的前一个RE字符。

例:在g与g之间有2到3个o存在的字符串,即(goog) (gooog)

grep -n 'go\{2,3\}g' regular.txt

    

 

    特别注意,正则表达式的特殊字符与一般在命令行输入命令的“通配符”并不相同~!举例来说,在不支持正则表达式的ls工具中,若我们使用“ls -|*”代表的是任意文件名的文件,而“ls -la*”代表的是以a为开头的任何文件名的文件,但在正则表达式中,我们要找到含有以a为开头的文件则必须使用以下语句:

ls | grep -n '^a.*'  

 

 

PS: 以上资料均来源于“鸟哥的Linux私房菜”. 

 

 

posted @ 2016-01-20 19:04  江湖小妞  阅读(391)  评论(0编辑  收藏  举报