文本处理三剑客(grep、sed、awk)

文本处理三剑客(grep、sed、awk)

剑客1-grep 文本过滤工具

grep介绍

grep (Global search REgular expression and Print out the line/全面搜索正则表达式并把行打印出来)、

grep一种强大的文本搜索工具,它能使用正则表达式搜索文本,并把匹配的行打印出来。

grep工作流程

grep的工作方式是这样的,它在一个或多个文件中搜索字符串模板。如果模板包括空格,则必须被引用,模板后的所有字符串被看作文件名。搜索的结果被送到标准输出,不影响原文件内容。grep可用于shell脚本,因为grep通过返回一个状态值来说明搜索的状态,如果模板搜索成功,则返回0,如果搜索不成功,则返回1,如果搜索的文件不存在,则返回2。我们利用这些返回值就可进行一些自动化的文本处理工作。

grep命令

格式如下:

grep [option] pattern file

常用选项:

  • -V: 打印grep的版本号

  • -E: 解释PATTERN作为扩展正则表达式,也就相当于使用egrep。 或操作

  • -F : 解释PATTERN作为固定字符串的列表,由换行符分隔,其中任何一个都要匹配。也就相当于使用fgrep。

  • -G: 将范本样式视为普通的表示法来使用。这是默认值。加不加都是使用grep。

匹配控制选项:

  • -e : 使用PATTERN作为模式。这可以用于指定多个搜索模式,或保护以连字符( - )开头的图案。指定字符串做为查找文件内容的样式。

  • -f : 指定规则文件,其内容含有一个或多个规则样式,让grep查找符合规则条件的文件内容,格式为每行一个规则样式。

  • -i : 搜索时候忽略大小写

  • -v: 反转匹配,选择没有被匹配到的内容。

  • -w:匹配整词,精确地单词,单词的两边必须是非字符符号(即不能是字母数字或下划线)

  • -x:仅选择与整行完全匹配的匹配项。精确匹配整行内容(包括行首行尾那些看不到的空格内容都要完全匹配)

  • -y:此参数的效果和指定“-i”参数相同。

一般输出控制选项:

  • -c: 抑制正常输出;而是为每个输入文件打印匹配线的计数。

  • --color [= WHEN]:让关键字高亮显示,如--color=auto

  • -L:列出文件内容不符合指定的范本样式的文件名称

  • -l : 列出文件内容符合指定的范本样式的文件名称。

  • -m num:当匹配内容的行数达到num行后,grep停止搜索,并输出停止前搜索到的匹配内容

  • -o: 只输出匹配的具体字符串,匹配行中其他内容不会输出

  • -q:安静模式,不会有任何输出内容,查找到匹配内容会返回0,未查找到匹配内容就返回非0

  • -s:不会输出查找过程中出现的任何错误消息,-q和-s选项因为与其他系统的grep有兼容问题,shell脚本应该避免使用-q和-s,并且应该将标准和错误输出重定向到/dev/null 代替。

上下文线控制选项:

  • -A num:匹配到搜索到的行以及该行下面的num行

  • -B num:匹配到搜索到的行以及该行上面的num行

  • -C num:匹配到搜索到的行以及上下各num行

实例演示

演示详情:Linux_文件查找

剑客2-sed 行编辑工具

sed介绍

sed是linux文本处理工具三剑客(grep,sed,awk)之一,用来处理文本的流编辑工具。主要用来编辑一个或多个文件,简化重复操作文件

sed是一种流编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区的内容,处理完成后,把缓冲区的内容送往屏幕。然后读入下行,执行下一个循环。如果没有使用诸如“D”的特殊命令,那会在两个循环之间清空模式空间,但不会清空保留空间。这样不断重复,直到文件末尾。文件内容并没有改变,除非使用重定向存储输出。

sed使用

调用sed有两种方法:

  • 在命令行上指定编辑指令
  • 放在一个文件中并提供这个文件的名字

sed语法

#
stdout | sed [option] "pattern command"
#
sed [option] "pattern command" file

常用option选项

选项 含义
-n 只打印模式匹配行(不会显示原行信息)
-e 直接在命令行进行sed编辑,默认选项,编辑随后的指令
-f 编辑动作保存在文件中,执行文件执行
-r 支持扩展正则表达式,跟随脚本中的文件名
-i 直接修改文件内容

只有在命令行上给出多个指令时才需要用-e选项。它告诉sed将以下参数解释为指令。当只有一个指令时,sed可以自己做决定。

使用简单的指令

创建一个名为list的样本文件,修改后与此对比

[root@localhost ~]# vim list

John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
  1. 没有加-i选项,所以没有修改文件的内容,只显示修改效果
#把MA替换Massachusetts
[root@localhost ~]# sed 's/MA/Massachusetts/' list 
John Daggett, 341 King Road, Plymouth Massachusetts
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury Massachusetts
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston Massachusetts
#源文件并没有改变
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
  1. 匹配一个位置,添加你要的内容
#匹配 MA,替换成, Massachusetts,注意空格也要加上去匹配
[root@localhost ~]# sed 's/ MA/, Massachusetts/' list 
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston, Massachusetts
  1. 用分号分隔指令
#使用分号分开,一次修改两个位置
[root@localhost ~]# sed 's/ MA/, Massachusetts/;s/ PA/, Pennsylvania/' list
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston, Massachusetts
  1. 在每个指令前放置-e
#使用-e分隔开,一次修改两个位置
[root@localhost ~]# sed -e 's/ MA/, Massachusetts/' -e 's/ PA/, Pennsylvania/' list
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston, Massachusetts
  1. 使用Bourne shell的分行指令功能,在输入单引号后按return键,就会出现多行输入提示符(>)
#分行指令功能
[root@localhost ~]# sed '
s/ MA/, Massachusetts/
s/ PA/, Pennsvlvania/
s/ CA/, California/ ' list
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsvlvania
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View, California
Sal Carpenter, 73 6th Street, Boston, Massachusetts

失误的命令

sed命令的语法可以被细化,在使用时很容易犯错误或者忽略掉需要的元素

注意输入以下不完整的语法将发生的情况:

[root@localhost ~]# sed -e 's/ MA/, Massachusetts' list
sed: -e expression #1, char 21: unterminated `s' command

sed 通常会显示任何它不能执行的行,但是它不会告诉你使用这个命令所发生的错误是什么。在上述情况下,标记搜索和替换命令末尾的斜杠丢失了。

脚本文件

在命令行上输入较长的编辑脚本是不实际的。这就是通常最好创建包含编辑指令的脚本文件的原因。编辑脚本只是一系列要依次的简单的sed命令。这种形式使用-f选项来指定命令行上的脚本文件的名字,格式如下:

sed -f scriptfile file

将想要执行的所有编辑命令都放置在文件中。我们按照惯例创建临时脚本文件sedscr

#下面的命令读取sedscr 中的所有替换命令,并将这些命令应用于输入文件list中的每一行:
[root@localhost ~]# vim sedscr

s/ MA/, Massachusetts/
s/ PA/, Pennsylvania/
s/ CA/, California/
s/ VA/, Virginia/
s/ OK/, Oklahome/
#查看list原文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#使用脚本文件sedsrc修改list文件
[root@localhost ~]# sed -f sedscr list
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond, Virginia
Orville Thomas, 11345 Oak Bridge Road, Tulsa, Oklahome
Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke, Virginia
Amy Wilde, 334 Bayshore Pkwy, Mountain View, California
Sal Carpenter, 73 6th Street, Boston, Massachusetts

保存输出

只有将sed的输出重定向到另一个程序中,才能够捕获文件中的输出。要完成这项工作需要在一个文件名后面指定一个shell的I/0重定向符号。例如:

sed -f sedsrc list > newlist

生成一个替换后的newlist新文件

#替换完内容后的文件定向到newlist文件
[root@localhost ~]# sed -f sedscr list > newlist
[root@localhost ~]# ls
anaconda-ks.cfg  list  newlist  sedscr
#查看list原文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#查看新文件
[root@localhost ~]# cat newlist 
John Daggett, 341 King Road, Plymouth, Massachusetts
Alice Ford, 22 East Broadway, Richmond, Virginia
Orville Thomas, 11345 Oak Bridge Road, Tulsa, Oklahome
Terry Kalkas, 402 Lans Road, Beaver Falls, Pennsylvania
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Hubert Sims, 328A Brook Road, Roanoke, Virginia
Amy Wilde, 334 Bayshore Pkwy, Mountain View, California
Sal Carpenter, 73 6th Street, Boston, Massachusetts

阻止输入行的自动显示

sed的默认操作是输出每个输入行,-n 选项可以阻止自动输出。当指定该选项时,每个要生成输出的指令都必须包含打印命令p。请看下面的示例:

#查看list原文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#只输出修改的部分
[root@localhost ~]# sed -n 's/ MA/, Massachusetts/p' list
John Daggett, 341 King Road, Plymouth, Massachusetts
Eric Adams, 20 Post ROad, Sudbury, Massachusetts
Sal Carpenter, 73 6th Street, Boston, Massachusetts

剑客3-awk文本处理工具

awk介绍

awk是linux文本处理工具三剑客(grep,sed,awk)之一,对文件进行格式化处理的,这里的格式化不是文件系统的格式化,而是对文件内容进行各种“排版”,进而格式化显示

awk工作流程

执行awk时,它会反复进行下列4步骤:

  1. 自动从制定的数据文件中读取一个数据行;

  2. 自动更新相关的内建变量,如:NR,NF,$0……;

  3. 依次执行程序中所有的Patten{Actions}指令;

  4. 当执行完程序中所有的Patten{Actions}时,若数据文件中还有未读取的数据,则反复执行步骤1到步骤4.

awk使用

与sed相似,awk为每个输入行执行一套指令。可以在命令行上指定指令或创建脚本文件。

awk语法

命令行的语法是:

awk [option]'command' files

用脚本文件调用awk 的语法如下:

awk -f script files

-f 选项的工作方式与在sed中相同

awk使用示例

尽管awk指令与sed指令的结构相同,都由模式和过程两部分组成,但过程本身有很大的不同。awk看上去不像编辑器而更像一种程序设计语言。语句和函数取代了使用一个或两二个字符组成的命令序列。例如,使用print 语句打印表达式的值或打印当前输入行的内容。

在通常情况下,awk将每个输入行解释为一条记录而将一行上的每个单词(由空格或制表符分隔)解释为每一个字段(可以改变这些默认设置)。一个或多个连续的空格或制表符看做一个定界符。awk 允许在模式或过程中引用这些字段。$O代表整个记录。我们来看几个示例,使用样本输入文件list.

  1. 第一个示例包含单个指令,用于打印输入文件中每行的第一个字段。
#查看list文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#打印出第一行
[root@localhost ~]# awk '{print $1}' list 
John
Alice
Orville
Terry
Eric
Hubert
Amy
Sal
  1. “$1”表示每个输入行上的第一个字段的值。因为这里没有指定模式,所以打印语句应用于所有的行。下一个示例指定了“/MA/”模式,但是其中没有过程。这个默认操作是打印匹配这种模式的每一行。
#查看list文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#打印出 MA一行,双//表示匹配
[root@localhost ~]# awk '/ MA/' list 
John Daggett, 341 King Road, Plymouth MA
Eric Adams, 20 Post ROad, Sudbury MA
Sal Carpenter, 73 6th Street, Boston MA
  1. 本例打印了3行。正如在第一章所提到的那样,awk程序更像一种查询语言,从文件中提取有用的信息。可以认为惟上模式指定了一种条件,用于选择要包括在报表中的记录,也就是这些记录必须包含字符串“MA”。现在还可以指定记录的哪些部分要包括在报表中。下一个示例使用一条print语句限制只输出每条记录的第一个字段。
#查看list文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#只打印 MA这一行
[root@localhost ~]# awk '/ MA/ { print $1 }' list 
John
Eric
Sal
  1. 在下一示例中,使用-F选项将字段分隔符改变为逗号。它使我们能够检索3个字段中的任一个:全称、街道地址或城市和州。
#查看list文件
[root@localhost ~]# cat list 
John Daggett, 341 King Road, Plymouth MA
Alice Ford, 22 East Broadway, Richmond VA
Orville Thomas, 11345 Oak Bridge Road, Tulsa OK
Terry Kalkas, 402 Lans Road, Beaver Falls PA
Eric Adams, 20 Post ROad, Sudbury MA
Hubert Sims, 328A Brook Road, Roanoke VA
Amy Wilde, 334 Bayshore Pkwy, Mountain View CA
Sal Carpenter, 73 6th Street, Boston MA
#使用,作为分隔符
[root@localhost ~]# awk -F, '/ MA/ { print $1 }' list 
John Daggett
Eric Adams
Sal Carpenter
#可以用''把,引起来
[root@localhost ~]# awk -F ',' '/ MA/ { print $1 }' list 
John Daggett
Eric Adams
Sal Carpenter
#不换行打印
[root@localhost ~]# awk -F ',' '/ MA/ { print $1;print $2;print3 }' list 
John Daggett
 341 King Road
Eric Adams
 20 Post ROad
Sal Carpenter
 73 6th Street
#使用,分隔符 不要print 不换行打印
[root@localhost ~]# awk -F ',' '/ MA/ { print $1,$2,$3 }' list 
John Daggett  341 King Road  Plymouth MA
Eric Adams  20 Post ROad  Sudbury MA
Sal Carpenter  73 6th Street  Boston MA
#不想用空格连接,使用---连接
[root@localhost ~]# awk -F ',' '/ MA/ { print $1,"---",$2,"---",$3 }' list 
John Daggett ---  341 King Road ---  Plymouth MA
Eric Adams ---  20 Post ROad ---  Sudbury MA
Sal Carpenter ---  73 6th Street ---  Boston MA
#使用---连接,但是不要空格
[root@localhost ~]# awk -F ',' '/ MA/ { print $1"---"$2"---"$3 }' list 
John Daggett--- 341 King Road--- Plymouth MA
Eric Adams--- 20 Post ROad--- Sudbury MA
Sal Carpenter--- 73 6th Street--- Boston MA

前面的示例使用sed改变了输入数据的内容。使用awk重新排列数据。在上面的 awk示例中,注意如何将前导空白看做是第二个和第三个字段的一部分。

出错信息

当遇到程序中的问题时,awk 的每个实现都会给出不同的出错信息。因此,这里不引用特殊版本的消息;当出现问题时它是显而易见的。下面任何一种情况都会产生消息:

  • 没有用大括号({})将过程括起来
  • 没有用单引号('')将指令括起来
  • 没有用斜杠(//)中将正则表达式括起来

awk命令行选项

选项 注释
-f 跟随脚本的文件名
-F 改变字段分隔符
-v 跟随var=valua
#直接定义一个变量a=10
[root@localhost ~]# echo |awk -va=10 '{print a}'
10

同时使用 sed和 awk

在unix 中,管道可用于将一个程序的输出作为输入传递给另一个程序。参看几个综合使用sed和 awk来产生报表的示例。用州的全名代替邮政编码的sed脚本通常已经足够,它可被再次用做名为nameState 的脚本文件:

[root@localhost ~]# cat nameState 
s/ MA/, Massachusetts/
s/ PA/, Pennsylvania/
s/ CA/, California/
s/ VA/, Virginia/
s/ OK/, Oklahome/

该程序(使用输入文件list)的输出,与我们已经看到的相同。在下一个示例中,由nameState产生的输出被输送到一个awk程序中,这个awk程序用于从每条记录中提取州的名字

[root@localhost ~]# sed -f nameState list |awk -F, '{print $4}'
 Massachusetts
 Virginia
 Oklahome
 Pennsylvania
 Massachusetts
 Virginia
 California
 Massachusetts

以上 awk程序处理由sed 脚本产生的输出。记住前面的sed 脚本用逗号和州的全称代替缩写。实际上,它将包含城市和州的第三个字段拆分成二个字段。“$4”表示第4个字段

这里所做的事情可以完全由sed 完成,但可能会有更多的困难和更少的通用性。而且,因为awk 允许替换匹配的字符串,所以可以完全用awk 脚本得到这个结果

本程序的结果不是非常有用,可以将它传递给sort luniq -c ,它将州名按字母表排序,同量给出每个州名出现的资料

按州的名字排序并列出州的名字,以及住在那个州的人的名字。下面的示例展示了byState程序:

[root@localhost ~]# cat byState 
awk -F, '{
    print $4 ", "$0
}' $* | sort |
awk -F, '
    $1 == LastState {
        print "\t" $2
    }
    $1 != LastState {
        LastState=$1
        print $1
        print "\t"$2
    }
'

这个shell脚本有3个部分。程序中调用awk以产生sort程序的输入,然后再次调用awk 测式排好序的输入,并确定当前记录中的州的名字,是否与前一个记录中的名字相同。我们来看这个脚本的执行:

[root@localhost ~]# sed -f sedscr list | ./byState
	 
 California
	 Amy Wilde
 Massachusetts
	 Eric Adams
	 John Daggett
	 Sal Carpenter
 Oklahome
	 Orville Thomas
 Pennsylvania
	 Terry Kalkas
 Virginia
	 Alice Ford
	 Hubert Sims

这些名字被按州排序。这是使用awk从结构化数据中生成报表的典型示例。

正则表达式

概念

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

简介

正则表达式是对字符串(包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”))操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。正则表达式是一种文本模式,该模式描述在搜索文本时要匹配的一个或多个字符串。

特点

正则表达式的特点是:

  1. 灵活性、逻辑性和功能性非常强;

  2. 可以迅速地用极简单的方式达到字符串的复杂控制。

  3. 对于刚接触的人来说,比较晦涩难懂。

由于正则表达式主要应用对象是文本,因此它在各种文本编辑器场合都有应用,小到著名编辑器EditPlus,大到Microsoft Word、Visual Studio等大型编辑器,都可以使用正则表达式来处理文本内容。

符号

元字符 描述
\ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\n”匹配\n。“\n”匹配换行符。序列“\”匹配“\”而“(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。
^ 匹配输入字行首。如果设置了RegExp对象的Multiline属性,^也匹配“\n”或“\r”之后的位置。
$ 匹配输入行尾。如果设置了RegExp对象的Multiline属性,$也匹配“\n”或“\r”之前的位置。
* 匹配前面的子表达式任意次。例如,zo能匹配“z”,也能匹配“zo”以及“zoo”。等价于{0,}。
+ 匹配前面的子表达式一次或多次(大于等于1次)。例如,“zo+”能匹配“zo”以及“zoo”,但不能匹配“z”。+等价于{1,}。
? 匹配前面的子表达式零次或一次。例如,“do(es)?”可以匹配“do”或“does”。?等价于{0,1}。
{n} n是一个非负整数。匹配确定的n次。例如,“o{2}”不能匹配“Bob”中的“o”,但是能匹配“food”中的两个o。
{n,} n是一个非负整数。至少匹配n次。例如,“o{2,}”不能匹配“Bob”中的“o”,但能匹配“foooood”中的所有o。“o{1,}”等价于“o+”。“o{0,}”则等价于“o*”。
{n,m} mn均为非负整数,其中n<=m。最少匹配n次且最多匹配m次。例如,“o{1,3}”将匹配“fooooood”中的前三个o为一组,后三个o为一组。“o{0,1}”等价于“o?”。请注意在逗号和两个数之间不能有空格。
? 当该字符紧跟在任何一个其他限制符(,+,?,{n},{n,},{n,m*})后面时,匹配模式是非贪婪的。非贪婪模式尽可能少地匹配所搜索的字符串,而默认的贪婪模式则尽可能多地匹配所搜索的字符串。例如,对于字符串“oooo”,“o+”将尽可能多地匹配“o”,得到结果[“oooo”],而“o+?”将尽可能少地匹配“o”,得到结果 ['o', 'o', 'o', 'o']
.点 匹配除“\n”和"\r"之外的任何单个字符。要匹配包括“\n”和"\r"在内的任何字符,请使用像“[\s\S]”的模式。
(pattern) 匹配pattern并获取这一匹配。所获取的匹配可以从产生的Matches集合得到,在VBScript中使用SubMatches集合,在JScript中则使用$0…$9属性。要匹配圆括号字符,请使用“(”或“)”。
(?:pattern) 非获取匹配,匹配pattern但不获取匹配结果,不进行存储供以后使用。这在使用或字符“(|)”来组合一个模式的各个部分时很有用。例如“industr(?:y|ies)”就是一个比“industry|industries”更简略的表达式。
(?=pattern) 非获取匹配,正向肯定预查,在任何匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如,“Windows(?=95|98|NT|2000)”能匹配“Windows2000”中的“Windows”,但不能匹配“Windows3.1”中的“Windows”。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern) 非获取匹配,正向否定预查,在任何不匹配pattern的字符串开始处匹配查找字符串,该匹配不需要获取供以后使用。例如“Windows(?!95|98|NT|2000)”能匹配“Windows3.1”中的“Windows”,但不能匹配“Windows2000”中的“Windows”。
(?<=pattern) 非获取匹配,反向肯定预查,与正向肯定预查类似,只是方向相反。例如,“(?<=95|98|NT|2000)Windows”能匹配“2000Windows”中的“Windows”,但不能匹配“3.1Windows”中的“Windows”。*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等
(?<!pattern) 非获取匹配,反向否定预查,与正向否定预查类似,只是方向相反。例如“(?<!95|98|NT|2000)Windows”能匹配“3.1Windows”中的“Windows”,但不能匹配“2000Windows”中的“Windows”。*python的正则表达式没有完全按照正则表达式规范实现,所以一些高级特性建议使用其他语言如java、scala等
x|y 匹配x或y。例如,“z|food”能匹配“z”或“food”(此处请谨慎)。“[z|f]ood”则匹配“zood”或“food”。
[xyz] 字符集合。匹配所包含的任意一个字符。例如,“[abc]”可以匹配“plain”中的“a”。
[^xyz] 负值字符集合。匹配未包含的任意字符。例如,“[^abc]”可以匹配“plain”中的“plin”任一字符。
[a-z] 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符。注意:只有连字符在字符组内部时,并且出现在两个字符之间时,才能表示字符的范围; 如果出字符组的开头,则只能表示连字符本身.
[^a-z] 负值字符范围。匹配任何不在指定范围内的任意字符。例如,“[^a-z]”可以匹配任何不在“a”到“z”范围内的任意字符。
\b 匹配一个单词的边界,也就是指单词和空格间的位置(即正则表达式的“匹配”有两种概念,一种是匹配字符,一种是匹配位置,这里的\b就是匹配位置的)。例如,“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”;“\b1_”可以匹配“1_23”中的“1_”,但不能匹配“21_3”中的“1_”。
\B 匹配非单词边界。“er\B”能匹配“verb”中的“er”,但不能匹配“never”中的“er”。
\cx 匹配由x指明的控制字符。例如,\cM匹配一个Control-M或回车符。x的值必须为A-Z或a-z之一。否则,将c视为一个原义的“c”字符。
\d 匹配一个数字字符。等价于[0-9]。grep 要加上-P,perl正则支持
\D 匹配一个非数字字符。等价于[^0-9]。grep要加上-P,perl正则支持
\f 匹配一个换页符。等价于\x0c和\cL。
\n 匹配一个换行符。等价于\x0a和\cJ。
\r 匹配一个回车符。等价于\x0d和\cM。
\s 匹配任何不可见字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何可见字符。等价于[^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于\x09和\cI。
\v 匹配一个垂直制表符。等价于\x0b和\cK。
\w 匹配包括下划线的任何单词字符。类似但不等价于“[A-Za-z0-9_]”,这里的"单词"字符使用Unicode字符集。
\W 匹配任何非单词字符。等价于“[^A-Za-z0-9_]”。
\xn 匹配n,其中n为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如,“\x41”匹配“A”。“\x041”则等价于“\x04&1”。正则表达式中可以使用ASCII编码。
*num* 匹配num,其中num是一个正整数。对所获取的匹配的引用。例如,“(.)\1”匹配两个连续的相同字符。
*n* 标识一个八进制转义值或一个向后引用。如果*n之前至少n个获取的子表达式,则n为向后引用。否则,如果n为八进制数字(0-7),则n*为一个八进制转义值。
*nm* 标识一个八进制转义值或一个向后引用。如果*nm之前至少有nm个获得子表达式,则nm为向后引用。如果*nm之前至少有n个获取,则n为一个后跟文字m的向后引用。如果前面的条件都不满足,若nm均为八进制数字(0-7),则*nm将匹配八进制转义值nm*。
*nml* 如果n为八进制数字(0-7),且ml均为八进制数字(0-7),则匹配八进制转义值nml
\un 匹配n,其中n是一个用四个十六进制数字表示的Unicode字符。例如,\u00A9匹配版权符号(©)。
\p 小写 p 是 property 的意思,表示 Unicode 属性,用于 Unicode 正表达式的前缀。中括号内的“P”表示Unicode 字符集七个字符属性之一:标点字符。其他六个属性:L:字母;M:标记符号(一般不会单独出现);Z:分隔符(比如空格、换行等);S:符号(比如数学符号、货币符号等);N:数字(比如阿拉伯数字、罗马数字等);C:其他字符。**注:此语法部分语言不支持,例:javascript。*
<> 匹配词(word)的开始(<)和结束(>)。例如正则表达式<the>能够匹配字符串"for the wise"中的"the",但是不能匹配字符串"otherwise"中的"the"。注意:这个元字符不是所有的软件都支持的。
( ) 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存9个),它们可以用 \1 到\9 的符号来引用。
| 将两个匹配条件进行逻辑“或”(or)运算。例如正则表达式(him|her) 匹配"it belongs to him"和"it belongs to her",但是不能匹配"it belongs to them."。注意:这个元字符不是所有的软件都支持的。

常用正则表达式

用户名 /[1]{3,16}$/
密码 /[2]{6,18}$/
十六进制值 /^#?([a-f0-9]{6}|[a-f0-9]{3})$/
电子邮箱 /^([a-z0-9_.-]+)@([\da-z.-]+).([a-z.]{2,6})$/ /[3]+(.[a-z\d]+)*@(\da-z?)+(.{1,2}[a-z]+)+$/
URL /^(https?😕/)?([\da-z.-]+).([a-z.]{2,6})([/\w .-])/?$/
IP 地址 /((2[0-4]\d|25[0-5]|[01]?\d\d?).){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)/ /^(?😦?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
HTML 标签 /<([a-z]+)([<]+)(?:>(.)</\1>|\s+/>)$/
删除代码\注释 (?<!http:|\S)//.*$
Unicode编码中的汉字范围 /[4]+$/

实例

匹配需要的电话号码

#电话列表
[root@localhost ~]# cat phonenum 
027-89332323
3978-673464
123-213452567
2345-4352235
#匹配0-9 -前面一段至少3次最多4次,-后面最少7次,最多8次的电话
[root@localhost ~]# grep -E '[0-9]{3,4}-[0-9]{7,8}' phonenum 
027-89332323
123-213452567
2345-4352235
#匹配0-9 -前面出现3次,-后面出现9次的电话
[root@localhost ~]# grep -E '[0-9]{3}-[0-9]{9}' phonenum 
123-213452567

  1. a-z0-9_- ↩︎

  2. a-z0-9_- ↩︎

  3. a-z\d ↩︎

  4. \u2E80-\u9FFF ↩︎

posted @ 2021-03-26 09:07  我爱吃芹菜~  阅读(175)  评论(0编辑  收藏  举报
Title