【shell】shell学习之正则表达式和sed命令

简介

        shell脚本语言包含了众多用于解决Unix/Linux系统问题的工具,其中有不少和文本处理相关,包括sed、awk、grep(awk和grep命令已经在前面的文章中进行了说明),这些工具可以相互结合以满足文本处理需求。

        正则表达式是一种基础的模式匹配技术。大多数文本处理工具都支持正则表达式,我们可以对文本文件执行过滤、剥离(strip)、替换、搜索等操作。

目录

正则表达式

1、正则表达式规则

规则1:位置标记锚点。

规则2:标识符。

规则3:数量修饰符。

规则4:一些其他的符号。

2、一些正则表达式含义

示例1:匹配任意单词的正则表达式

示例2:匹配IP地址,IP地址是由点号分隔的4组三位数字。

示例3:匹配电子邮件地址的正则表达式。

sed命令处理文本

1、sed命令进行文本替换

示例1:在文本中对特定的匹配模式进行字符串替换。

示例2:在文本中对特定的匹配模式进行字符串的全局替换。

示例3:选项-i会使得sed用修改后的数据替换原始文件。

示例4:更改分隔符。

示例5:已匹配的字符串的标记,使用“&”这一符号标记。

示例6:子串匹配标记。可以用\1,\2,……表示子模式匹配到的内容。

示例7:在sed命令中使用变量,双引号就派上用场了。

​编辑 

2、sed命令在文本中添加一行或删除一行

示例1:使用“d”移除文件中的特定行

 示例2:使用“a”在文本指定行后面添加一行。

示例3:使用“i”在文本指定行前面添加一行。 


正则表达式

        正则表达式是由字面文本和具有特殊意义的符号组成的。我们可以根据需要,构造出合适的正则表达式来匹配任何文本。要想使用正则表达式需要先了解正则表达式的规则。

1、正则表达式规则

规则1:位置标记锚点。

        有时候需要匹配“以xxx开头”或“以xxx结尾”的文本,就需要标记匹配文本的位置。

正则表达式描述示例
^匹配以正则表达式的文本开头的字符串^tux能匹配以tux起始的行
$匹配以正则表达式的文本结尾的字符串tux$能匹配以tux结尾的行
规则2:标识符。

        标识符是正则表达式的基础组成部分,它定义了匹配特定的文本必须存在(或不存在)的字符。

正则表达式描述示例
A(字符的代称)正则表达式必须匹配该字符A能够匹配A
.匹配任意一个字符appl.能够匹配apple和apply,但是不能匹配apples
[ ]匹配中括号内的任意一个字符。中括号内可以是一个字符组或字符范围coo[kl]能够匹配cook]和cool,[0-9]匹配任意单个数字
[^ ]匹配不在中括号内的任意一个字符。中括号内可以是一个字符组或字符范围23[^45]可以匹配236和237,但是不能匹配234和235;A[^0-9]匹配A以及随后的任意非数字单个字符
规则3:数量修饰符。

        一个标识符可以出现一次、多次或不出现。数量修饰符定义了模式可以出现的次数。

正则表达式描述示例
匹配之前的项1次或0次colou?r能够匹配color和coloour
+匹配之前的项1次或多次Rollno-9+能够匹配Rollno-9和Rollno-99,但是不能匹配Rollno-
*匹配之前的项0次或多次co*l能够匹配cl、col和coool
{n}匹配之前的项n次[0-9]{3}能够匹配任意的三位数,[0-9]{3}等价于[0-9][0-9][0-9]
{n, }之前的项至少需要匹配n次[0-9]{2,}能够匹配任意一个两位或更多位数字
{n,m}之前的项最少匹配n次,最多匹配m次[0-9]{2,5}能够匹配两位数到五位数之间的任意一个数字
规则4:一些其他的符号。
正则表达式描述示例
()将括号中的内容视为一个整体ma(tri)?x可以匹配max和matrix
|指定了一种选择,可以匹配 | 两边的任意一项Oct (1st | 2nd)能够匹配Oct 1st或Oct 2nd
\转义字符,可以转移之前介绍的特殊字符a\.b可以匹配a.b,而不是在二者中间匹配任意一个字符

2、一些正则表达式含义

        熟悉了上面介绍的正则表达式的规则,接下来可以尝试解读一下复杂的正则表达式。

示例1:匹配任意单词的正则表达式

( +[a-zA-Z]+ +)

开头的加号匹配一个或多个空格,[a-zA-Z]用于匹配任意一个大写或小写字母,其后的加号表示至少匹配1个大写或小写字母,最后的加号表示需要匹配一个或多个空格来终结单词。

        如果考虑到匹配句子末尾的单词,可以将句子末尾的标点符号放入正则表达式:

( +[a-zA-Z]+[?,.]? +)

[?,.]?匹配问号,逗号或点号中的一个,0次或1次(也就是有或者没有标点符号)。

示例2:匹配IP地址,IP地址是由点号分隔的4组三位数字。

[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

#也可以用[[:digit:]]表示数字,写成如下形式:

[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}

注:上面的正则表达式可以匹配文本中的IP地址,但是并不检查地址的合法性。 

示例3:匹配电子邮件地址的正则表达式。

[a-zA-Z0-9._]+@[a-zA-Z0-9.]+\.[a-zA-Z]{2,4}

电子邮件的地址采用“name@domain.some_2-4_letter”这种形式命名,[a-zA-Z0-9._]+表示匹配大小写字母、数字、下划线和点号1次或多次,@后的domain“[a-zA-Z0-9.]+”表示匹配大小写字母、数字和点号1次或多次,后面匹配一个点号,用\进行转义,[a-zA-Z]{2,4}能够匹配长度为2、3或4的字符串。

sed命令处理文本

1、sed命令进行文本替换

        sed是stream editor(流编辑器)的缩写。它最常见的用法是进行文本替换。

示例1:在文本中对特定的匹配模式进行字符串替换。
$ sed 's/pattern/replace_string/' file

其中pattern可以是简单的字符串或正则表达式,需要注意的是,正则表达式中“\d”表示一个十进制数,但在sed命令里,必须用[0-9]来表示,正则表达式中的“+”和“?”,在sed命令中也要加上反斜杠即:“\+”和“\?”。 

例如:将file.txt文件中的text替换为test.

$ sed 's/text/test/' file.txt
  示例2:在文本中对特定的匹配模式进行字符串的全局替换。

         上面的命令只替换每行中第一次出现的text,如果想将文本中所有text全部替换,需要使用g标记,具体如下:

$ sed 's/text/test/g' file.txt

g标记可以使sed替换第N次出现的匹配:

$ echo thisthisthisthis | sed 's/this/THIS/2g'

结果:从每行的第2个开始进行替换

$ echo -e "thisthisthisthis\nthisthisthisthis" | sed 's/this/THIS/3g'

 结果:从每行的第3个开始进行替换

$ echo -e "thisthisthisthis\nthisthisthisthis" | sed 's/this/THIS/4g'

  结果:从每行的第4个开始进行替换

示例3:选项-i会使得sed用修改后的数据替换原始文件。

例如 :file.txt文件的内容如下:

This is a text.The text is a special thing.First,we need install make and gcc.
second,the text also need to install package.

$ sed 's/text/test/g' file.txt

使用这一命令的结果为:将文本中所有text替换为test

但是file.txt文件中的内容并没有修改, 加入-i参数后,则可修改原文的内容,

示例4:更改分隔符。

        上面的sed命令中,s之后的/字符被视为命令分隔符,这是默认的,我们也可以使用其他分隔符,例如:

$ sed 's:text:test:g' file.txt
#或
$ sed 's|text|test|g' file.txt
示例5:已匹配的字符串的标记,使用“&”这一符号标记。

        在sed中,我们可以用&指代模式所匹配到的字符串,这样就能在替换字符串时使用已匹配的内容。例如:

$ echo this is an example | sed 's/\w\+/[&]/g'

 该命令是将这一文本中每一个单词用中括号括起来。\w也是常用的正则表达式符号,用于匹配大小写字母、数字或下划线,“+”表示匹配之前的项1次或多次,在sed命令中要使用”\+“(加上反斜杠),匹配到单词后,用“[&]”替换它,“&”对应匹配到的单词。

结果:

示例6:子串匹配标记。可以用\1,\2,……表示子模式匹配到的内容。

        在sed命令中,放在括号中的部分正则表达式表示子模式,也就是用这部分正则表达式匹配子串。例如:

$ echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'

该命令是将“digit 7”替换为“7”.其中\(pattern\)用于匹配子串(子模式放入使用反斜杠转义过的括号中),本例中 \([0-9]\)匹配到的子串是7.匹配到的第一个子串,对应标记是\1,匹配到的第二个子串标记是\2,以此类推。

结果:

例如:

$ echo seven EIGHT | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'

 “\([a-z]\+\)”用于匹配小写字母的单词,匹配结果标记为\1,“\([A-Z]\+\)”用于匹配大写字母的单词,匹配结果标记为\2,匹配完成后,替换时“\2 \1”相当于将第一个和第二个匹配结果换序了。

结果:

示例7:在sed命令中使用变量,双引号就派上用场了。

例如:

$ text=hello
$ echo hello world | sed "s/$text/HELLO/"

结果:

 

2、sed命令在文本中添加一行或删除一行

编辑命令含义
d删除文本中特定的行
a在指定行后增加一个新行,新增行的内容是"a"后面带的文本
i在指定行前增加一个新行,新增行的内容是"i"后面带的文本
示例1:使用“d”移除文件中的特定行
$ sed '/pattern/d' file #删除file中pattern匹配到的行

$ sed '2d' file  #删除file文本中的第二行,也可以换成其他数字

$ sed '1,4d' file    #删除file文本中的第一行到第四行(包含第一行和第四行)

$ sed '$d' file     #删除file中的最后一行

例如:

test.txt 内容如下:

This is a test.The test is a special thing.

First,we need install make and gcc.
second,the test also need to install package.
third, we need other preparations.

for example,the version of os should be 3.2.

①删除test.txt中包含“test”的行

$ sed '/test/d' test.txt

结果: 删除了包含test看的行,但是并没有更改原文件的内容,如需更改,需要加上-i选项。

 ②删除test.txt中的空行。

$ sed '/^$/d' test.txt  #删除文本中的空行

 空行可以用正则表达式“^$”匹配,/d告诉sed不执行替换操作,而是直接删除匹配到的空行。

结果:

 示例2:使用“a”在文本指定行后面添加一行。
$ sed '2a\This is a sample.' file  #在file的第二行后面添加一行,内容为"This is a sample."

$ sed '$a\This is a sample.' file  #在file文本最后添加一行,内容为"This is a sample."

例如:

$ sed '3a\this is a sample.' test.txt   #在第三行后添加一行

$ sed '$a\this is a sample.' test.txt   #在最后一行后添加一行

示例3:使用“i”在文本指定行前面添加一行。 
$ sed '2i\hello world.' file  #在file的第二行前面添加一行,内容为"hello world."

$ sed '$i\hello world.' file  #在file文本最后一行前面添加一行,内容为"hello world."

例如: 

$ sed '2i\hello world.' test.txt

结果:

$ sed '$i\hello world.' test.txt

结果:

 

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值