【转】sed正则表达式
1 正则表达式简介
2 正则表达式元字符和格式
在上一节里我们用一个例子介绍了什么是正则表达式的“元字符”。其实,元字符是一个或一组代替个或多个字符的字符。听起来有点拗口,但举一个例子也许你就明白了:元字符*用来匹配一个或多个的前一字符;而元字符 . 用来匹配一个任意的一个字符。正则表达式也可以不使用任何的元字符,一个简单的字符串 /piano/ (在Unix里正则表达式通常用一对斜线作为分隔符,后文在“正则表达式格式”部分中有介绍)也是一个正则表达式,只不过是准确匹配罢了。
元字符 |
功能
|
示例
|
匹配结果
|
^
|
行首定位符
|
/^supinfo/
|
匹配所有以supinfo开头的行
|
$
|
行尾定位符
|
/supinfo$/
|
匹配所有以supinfo结尾的行
|
\<
|
词首定位符
|
/\<supinfo/
|
匹配出现以supinfo为开头的词的行
|
\>
|
词尾定位符
|
/supinfo\>/
|
匹配出现以supinfo为结尾的词的行
|
.
|
匹配一个字符
|
/su…fo/
|
包含su,后面紧跟三个任意字符,然后紧跟着fo的行
|
*
|
匹配0个或多个前一字符
|
/_*supinfo/
|
supinfo前有0个或多个下划线的行
|
[]
|
匹配一组字符里的任意字符
|
/[Ss]pinfo/
|
包含Supinfo或supinfo的行
|
[x-y]
|
匹配指定范围内的字符
|
/[A-Z0-9]supinfo/
|
supinfo之前有一个A到Z或0到9的字符
|
[^ ]
|
匹配不在指定范围内的字符
|
/[^A-Z0-9]supinfo/
|
supinfo之前有一个既不是A到Z又不是0到9的字符
|
x\{m\}
x\{m,\}
x\{m, n\}
|
根据字符x出现的次数匹配:
m次;大于等于m次;大于等于m次但小于等于n次
|
/s\{2,5\}/
|
匹配有2到5个连续出现的s的行
|
\
|
转义元字符
|
/supinfo\. /
|
匹配包含supinfo,然后后面紧跟一个句点的行(没有 \ 的时候是匹配一个字符)
|
\(…\)
|
创建一个字符标签
|
/(SUPINFO):use\1NE/
|
括号中的字符被保存在标号为1的标签里,以后可以用\1来引用。标签编号从左到右依次为1,2,3……最多可以有9个标签。这个例子查找的是SUPINFO:后面跟着一个 use SUPINFONE的字符串
|
3 正则表达式实例解析
下面我们就以具体的实例来看一下如何使用正则表达式。其中用黑体着重标出的是匹配到的字符串。
一个最简单的例子便是 /all/,比如下面一段文字:
John’s ball fell into the hole
John cried because it is all his life.
这个正则表达式不含任何的原字符,它查找的是字符串all,这个字符串all可以是独成一个单词,也可以是其它单词的一部分,因此正则表达式/all/既匹配ball里的all,也匹配完整的单词all。
下面我们着重讨论正则表达式里原字符的用法。
3.1 行首、行尾定位符
行首定位符^
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/^Bobby/
匹配位于行首的Bobby。
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/Bobby$/
匹配位于行尾的Bobby。
3.2 词首、词尾定位符
词首定位符 \<
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/\<Bo/
匹配位于词首的字符串Bo。
词尾定位符 \>
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby
Bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/ball\>/
匹配位于词尾的字符串ball。
在一个表达式中搭配使用词首定位符与词尾定位符
John’s ball fell into the hole
John cried because it is his whole life
/\<hole\>/
匹配以h作为单词开头并且以e作为单词结尾的模式hole。也就是说,字母h的前面是一个分隔单词的字符(比如空格或换行符),字母l的后面也是一个分隔单词的字符。这样,在这个例子中只有完整的单词hole会被匹配,而单词whole就不会被匹配。
3.3 匹配单个字符
匹配任意的一个字符 .
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/B…y/
匹配B开头后面紧跟三个任意字符,最后紧接着一个y的字符串。在这个例子中,Bobby和Bippy都会被匹配。
匹配0个或多个前一字符 *
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck balll
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/ al*/
这里的星号(*)匹配0个或多个在它前面的那个字符。前面曾提到过,正则表达式里的*和shell里的*作用是截然不同的。在shell里*表示任意个数的任意字符,而在正则表达式里,*只代表任意个数(包括0个)的前一字符,*可以看作和它前面那个字符是粘连在一起的,*只限制它前面那一个字符。这个正则表达式中的*匹配单独一个或多个连续的l,甚至也匹配一个l也没有的模式,所以,单个字符a也会被匹配。
3.4 匹配多个字符
匹配一组字符里的任意字符 [ ]
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck balll
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/[bw]all/
方括号匹配一组字符中的一个,这个正则表达式查找的是第一个字母是b或w,后面紧跟着all的字符串,因此在这个例子中,wall和ball都会被匹配。
匹配指定范围内的字符 [x-y]
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/B[a-z]p/
方括号里的短线(-)匹配某一范围内的一个字符,这个正则表达式将查找第一个字母是B,第二个字母是ASCII码介于a到z的字符(小写字母),第三个字母是p的字符串。
匹配不在指定范围内的字符 [^ ]
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/all[^A-Z0-9]/
方括号内的脱字符^是一个否定字符,这个正则表达式查找的是后面带一个特殊字符的all,这个特殊字符既不是小写字母又不是大写字母,也不是0到9的数字,比如它可以是一个标点符号或空格。
根据字符x出现的次数匹配 x\{m\} x\{m,\} x\{m, n\}
比如这个正则表达式:/Go\{2,5\}gle/将匹配G后面至少出现2个,最多有不超过5个o的模式。Google,Goooogle会被匹配,而Gogle和Goooooogle则不会被匹配。
3.5 转义字符
如果要匹配的字符串中含有正则表达式的原字符,需要用斜线将其转义,就像c语言里打印单引号 ’ 要写成 \’ 一样。这里有个例子:我们想要查找字符串google.com,要查找的字符串里含有正则表达式的原字符“.”,因此这个正则表达式要写成 /google\.com/,如果不用 \转义,找到的将是google后面跟一个任意的字符,然后跟一个com的字符串。这显然不一定是我们要找的。
3.6 字符标签
例如在下面一段文字里:
Occurence and happening are the most general. I mean, the words occurence and happening are most generally used.
在这段文字里有两个拼错的单词,Occurence和occurence,(其实应该是occurrence),我们可以在vi中用下面的表达式将其修改:
:1,$s/\([Oo]ccur\)ence/\1rence/
我们且不管这个vi命令的用法(其实它是一个替换命令,我们在后面介绍sed时还将提到)我们先拿出这个语句中的两个表达式:
/\([Oo]ccur\)ence/
\1rence
其中前一个是一个正则表达式。这个命令用后面的表达式内容替换前面的正则表达式匹配到的内容。vi编辑器将查找单词Occurence和occurence,如果找到,就把圆括号中的内容加上标签(Occur或occur被加上标签),因为这是第一个被标记的模式,所以被称为标签1。这个模式被保存在称为寄存器1的内存寄存器中。在第二个正则表达式中用\1引用寄存器1中的内容,\1被替换为寄存器中的内容,后面紧跟一个rence,于是,拼错的Occurence和occurence被改正为正确的Occurrence和occurrence。
3.7 原字符组合使用的例子
例1:/\<Bob.*all\>/
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/\<Bob.*all\>/
匹配以Bob开头,后面跟任意个数的任意字符,然后以all结尾的字符串。这里再次重复, *在Shell里表示任意个数的任意字符,而在正则表达式里表示任意个数的前一字符。与 . 配合使用表示任意个数(包括零个)的任意字符。实际上,* 也可以表示重复零次或任意次它前面的一组字符,我们称这一组(有时也可能是一个)字符为“原子”。当原子包括多个字符时,这多个字符要用圆括号括起来,并且需要将圆括号转义;当原子只含一个字符时,可以不用圆括号。在这个例子里,. 表示一个任意字符,紧跟着一个*表示重复0次或任意次前面的那个任意字符。而下面的例子
/\(sup\)*info/
则表示匹配在字符串info前有0个或多个sup的字符串,因此 supinfo, info, supsupinfo都会被匹配。
例2:/B[a-z][bp]*y$/
Here is a tongue twister:
Bobby Bippy bought a bat.
Bobby Bippy bought a ball.
With his bat Bob banged the ball
Banged it bump against the wall
But so boldly Bobby banged it
That he burst his rubber ball, "Boo!" cried Bobby
Bad luck ball, Bad luck Bobby, bad luck ball
Now to drown his many troubles
Bobby Bippy's blowing bubbles.
/B[a-z][bp]*y$/
这个正则表达式匹配这样的字符串:开头字符是B,第二个字母是一个小写字母,后面紧跟0个或多个重复的b或p,最后跟一个y,并且这个字符串位于行的末尾。
4 sed原理及sed命令格式
4.1 Sed工作原理
sed是一个非交互式的流编辑器。所谓非交互式,是指使用sed只能在命令行下输入编辑命令来编辑文本,然后在屏幕上查看输出;而所谓流编辑器,是指sed每次只从文件(或输入)读入一行,然后对该行进行指定的处理,并将结果输出到屏幕(除非取消了屏幕输出又没有显式地使用打印命令),接着读入下一行。整个文件像流水一样被逐行处理然后逐行输出。
下面我们看一下sed的工作过程。
sed不是在原输入上直接进行处理的,而是先将读入的行放到缓冲区中,对缓冲区里的内容进行处理,处理完毕后也不会写回原文件(除非用shell的输出重定向来保存结果),而是直接输出到屏幕上。sed运行过程中维护着两个缓冲区,一个是活动的“模式空间(pattern space)”,另一个是起辅助作用的“暂存缓冲区(holding space)”。一般情况下,每当运行sed,sed首先把第一行装入模式空间,进行处理后输出到屏幕,然后将第二行装入模式空间替换掉模式空间里原来的内容,然后进行处理,以此类推。
一般情况下暂存缓冲区是用不到的,但有特殊的命令可以在模式空间与暂存缓冲区之间交换数据,后文将有介绍。由于sed对文本的所有操作都是在缓冲区里进行的,所以不会对原文件造成任何破坏。
4.2 Sed命令格式
sed的命令格式如下:
sed [-Options] [‘Commands’] filename
其中,Command是一个sed命令,sed命令一定要被包含在一对单引号中,以免被shell解释,其格式如下:
[address-range][sed-command]或
[Pattern-to-match][sed-command]
address-range是指要处理的行的范围,又叫地址范围;pattern-to-match是一个要匹配的模式,是一个正则表达式,sed-command是一个sed命令,用来对指定的行进行处理。下面是一个简单的例子:
sed –n ‘1,3p’ students
这个命令将文件students中的第1到3行打印到屏幕。注意,地址范围和sed命令之间没有空格,如果加入空格,sed也会将其忽略。参数-n用来取消默认输出。默认情况下,sed每读入一行到模式空间,无论是否对其进行处理,在读入下一行之前多要将模式空间中的内容输出到屏幕上。参数-n可以用来取消这种默认的输出,只有当用户用命令p时才将指定的行输出到屏幕。如果没有用参数-n而又对指定行执行了p命令,那么这些行将会被打印两次。
地址范围可以是一个数字,这个数字代表了一个行号;也可以是一个用逗号分隔的两个数字表示的范围(包括这两行)。范围可以是数字,正则表达式,或是两者的组合。
pattern-to-match是一个要匹配的模式,sed将会对所有匹配的行执行sed-command。其实,这里的pattern-to-match也可以看作是一个地址,这个地址是所有与指定模式匹配的行的行号。因此sed的格式可以归纳为一种:
sed [-Options] ‘[address-range][sed-command]’ filename
5 sed命令与选项
5.1 Sed命令
常用的sed命令如下表所列:
命令 |
功能 |
a\ |
在当前行之后插入一行或多行 |
c\ |
用新文本替换当前行中的文本,并开始新的一轮sed命令的执行 |
d |
删除行 |
i\ |
在当前行之前插入文本 |
h |
将模式空间里的内容拷贝到暂存缓冲区并替换原来暂存缓冲区的内容 |
H |
将模式空间里的内容追加到暂存缓冲区 |
g |
将里暂存缓冲区的内容拷贝到模式空间并替换原来模式空间的内容 |
G |
将暂存缓冲区里的内容追加到模式空间 |
p |
打印模式空间的内容 |
n |
读入下一行到模式空间,并接着从下一条命令开始执行 |
q |
直接退出sed,不继续执行其后的命令 |
r |
读入指定文件的内容 |
w |
将行写入文件 |
! |
对所选行以外的行进行处理 |
s/regexp/replacement/flag |
用replacement替换模式空间由regexp匹配到的内容
|
x |
交换模式空间与暂存缓冲区的内容 |
y/source-chars/dest-chars/ |
将source-chars的字符换成对应的的dest-chars中的字符,source-chars和dest-chars中的字符个数要相同。source-chars和dest-chars中都不能有正则表达式。 |
= |
打印当前行的行号,行号是令起一行打印的 |
# |
sed脚本文件中领起注释 |
替换命令s/regexp/replacement/flag 中的flag:
flag |
功能 |
g |
进行全局替换。不使用此选项将只对该行匹配到的第一个结果进行替换 |
p |
打印模式空间中的内容(替换之后的内容) |
w filename |
将替换之后的内容写入文件filename |
在后面的章节“sed实例解析”中我们将以实例的形式详细介绍各个命令的用法。
【转】sed正则表达式的更多相关文章
- sed正则表达式
sed的正则匹配如何实现非贪婪? sed的正则用的是BREs/EREs,不支持非贪婪模式.当然有一些方法可以实现非贪婪,比如: $ echo abcOabcdOabc | sed 's/.*O//' ...
- Linux基础-sed+正则表达式
1,删除文件每行的第一个字符:sed -r 's/^.//g' passwd 2,删除文件每行的第二个字符:sed -r 's/^(.)(.)/\2/g' passwd 3,删除文件每行的最后一个字符 ...
- 【原创】sed正则表达式替换
1.数字替换原数字 sed -i "s/\([0-9]*\)/\1/g"
- sed正则表达式匹配,各种括号的转义和不转义
https://blog.csdn.net/zl87758539/article/details/77481679
- 学习笔记之Shell脚本学习指南 & sed与awk & 正则表达式
正则表达式_百度百科 http://baike.baidu.com/link?url=ybgDrN2WQQKN64_gu-diCqdeDqL8LQ-jiQ-ftzzPaNUa9CmgBRDNnyx50 ...
- 正则表达式(BREs,EREs,PREs)差异比较
我想各位也和我一样,再linux下使用grep,egrep, awk , sed, vi的搜索时,会经常搞不太清楚,哪此特殊字符得使用转义字符'\' .. 哪些不需要, grep与egrep的差异 ...
- 【转】linux shell 正则表达式(BREs,EREs,PREs)差异比较
我想各位也和我一样,再linux下使用grep,egrep, awk , sed, vi的搜索时,会经常搞不太清楚,哪此特殊字符得使用转义字符'\' .. 哪些不需要, grep与egrep的差异 ...
- linux shell 正则表达式(BREs,EREs,PREs)差异比较
linux shell 正则表达式(BREs,EREs,PREs)差异比较 则表达式:在计算机科学中,是指一个用来描述或者匹配一系列符合某个句法规则的字符 串的单个字符串.在很多文本编辑器或其他工具里 ...
- linux中sed命令的使用
sed命令是linux或者shell编程中常用的筛选.替换命令,如果能熟练使用sed则对经常使用的人来说在工作上是非常有帮助的 下面把sed主要的用法列出来(有错误的地方大家可以指正): p命令只打印 ...
随机推荐
- [转]-nohup-真正的Shell后台运行
&方式: Unix/Linux下一般想让某个程序在后台运行,很多都是使用 & 在程序结尾来让程序自动运行. 比如我们要运行mysql在后台: /usr/local/mysql/bin/ ...
- MVVM 框架解析之双向绑定
更好的阅读体验,点击 原文地址 MVVM 框架 近年来前端一个明显的开发趋势就是架构从传统的 MVC 模式向 MVVM 模式迁移.在传统的 MVC 下,当前前端和后端发生数据交互后会刷新整个页面,从而 ...
- JavaScript基础知识(正则表达式、字符串)
23.正则表达式 作用:定义一个特定的验证字符串内容规则的表达式 注:正则表达式并不是JavaScript独有的:JavaScript支持正则表达式 var a = { }; // 定义一个空对象 ...
- JAVA基础-File类
一.File类概述 File类是文件和目录路径名的抽象表示形式.File类可以理解为一个文件路径或者文件夹路径的JAVA表现形式,而路径又可以分为绝对路径(是一个固定路径,从盘符开始),相对路径(相对 ...
- React Native 网络层分析
文:志俊(沪江Web前端) 本文原创,转载请注明作者及出处 在使用React Native开发中,我们熟练的采用JavaScript的方式发送请求的方式发送一个请求到服务端,但是处理这个请求的过程其实 ...
- makefile在编译的过程中出现“except class name”
今天写了部分代码,在添加到项目中后就那些编译,出现问题如下: logistic_regression_layer.h::: error: expected class name public Laye ...
- CVE-2017-8464复现 (远程快捷方式漏洞)
我们的攻击机IP是192.168.222.133 目标机IP是192.168.222.132 我们首先生成一个powershell msfvenom -p windows/x64/meterprete ...
- [51nod1532]带可选字符的多字符串匹配
有一个文本串,它的长度为m (1 <= m <= 2000000),现在想找出其中所有的符合特定模式的子串位置. 符合特定模式是指,该子串的长度为n (1 <= n <= 50 ...
- WEB 小案例 -- 网上书城(一)
距离上次写博客有两周了吧,最多的原因就是自己期末考试了,上课没听就只能在期末狠狠的复习了,毕竟已经挂科了.当然还是因为自己懒吧!!!废话不多说开始我们今天的正题,网上书城! 一. 新建数据表(MySQ ...
- .24-浅析webpack源码之事件流compilation(2)
下一个compilation来源于以下代码: compiler.apply(new EntryOptionPlugin()); compiler.applyPluginsBailResult(&quo ...