linux--sed命令

一、使用sed编辑器的好处

有些时候,你会发现想要自动处理文本文件中的文本,而不需要拉出全副武装的交互式文本编辑器。这种情况下,有个能够自动地格式化、插入、修改或删除文本元素的简单命令行编辑器就方便多了。Linux系统提供了具备该功能的编辑器,例如sed和gawk,本文主要介绍sed编辑器。

二、sed编辑器的简介

sed编辑器被称为流编辑器(stream editor)。
普通的交互式文本编辑器比如vim,可以用键盘命令来交互式插入、删除或替换数据中的文本。
流编辑器则会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。

sed是一个很好的文件处理工具,本身是一个管道命令,主要是以为单位进行处理,可以将数据行进行替换、删除、新增、选取等特定工作。sed编辑器可以基于输入到命令行的或是存储在命令文本文件中的命令来处理数据流中的数据。它每次从输入中读取一行,用提供的编辑器命令匹配数据、按命令中指定的方式修改流中的数据,然后将生成的数据输出到STDOUT。在流编辑器将所有命令与一行数据匹配之后,会读取下一行进行相同的操作直到最后一行。

三、sed命令的用法

3.1 从命令行读取命令和从文件读取命令

1、 在命令行定义编辑器命令
默认情况下,sed编辑器会将指定的命令应用到STDIN输入流上,这样可以直接将数据管道输出到sed编辑器上处理。

示例1$echo "This is a test" | sed 's/test/big test/'
This is a big test

sed命令几乎瞬间就执行完并返回数据。
注意:sed编辑器自身不会修改文本文件的数据。它只会将修改后的数据发送到STDOUT。如果查看原来的文本文件,它仍然保留着原始数据。

2、 在命令行使用多个编辑器命令
要在sed命令行上执行多个命令时,用-e选项就可以了。命令之间用分号分隔,并且在命令末尾和分号之间不能有空格。也可以用bash shell中的次提示符来分隔命令。

data1中的数据
$cat data1
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$
$ sed -e 's/brown/green/; s/dog/cat/' data1
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
The quick green fox jumps over the lazy cat.
$

注意:要在封尾单引号所在行结束命令。bash shell一旦发现了封尾的单引号,就会执行命令。然后将sed命令行中的每条命令作用到文本文件中的每一行上。

3、 从文件中读取编辑器命令
如果有大量要处理的sed命令,将它们放在一个文件中会更方便,可以在sed命令中用-f选项来指定文件。

$ cat script1
s/brown/green/
s/fox/elephant/
s/dog/cat/
$
$sed -f script1 data1
The quick green elephant jumps over the lazy cat.

这里不需要每条命令后面放一个分号,sed编辑器知道每行都有一条单独的命令。跟在命令行输入命令一样,sed编辑器会从指定文件中读取命令,并将它们应用到数据文件中的每一行上。

总结一下sed命令行格式为:

 sed [-nefri] ‘command’ 输入文本      

常用选项:

-n∶使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN的资料一般都会被显示到屏幕上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e∶直接在命令行模式上进行多个 sed 的动作编辑;
-f∶直接将 sed 的动作写在一个文件中, -f filename 则可以执行 filename 内的sed 动作;
-r∶sed 的动作支援的是延伸型正规表示法的语法。(预设是基础正规表示法语法)
-i∶直接修改读取的文件内容,而不是由屏幕输出。   
3.2 sed命令

常用命令如下:

a∶新增,a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
c∶取代,c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d∶删除,因为是删除啊,所以 d 后面通常不接任何东西;
i∶插入,i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p∶列印,亦即将某个选择的资料印出。通常 p 会与参数 sed -n 一起运作~
s∶取代,可以直接进行取代的工作。通常这个 s 的动作可以搭配正规表示法。例如 1,20s/old/new/g 就是啦!

1、替换标记
substitute命令在替换多行中的文本时能正常工作,默认情况下只替换每行中出现的第一处。要让替换命令对一行中不同地方出现的文本起作用,必须使用替换标记,替换标记会在替换命令字符串之后设置。

s/pattern/replacement/flags
替换标记:
数字,表明新文本讲替换第几处模式匹配的地方;
g,表明新文本将会替换所有已有文本出现的地方;
p,表明原来行的内容要打印出来
w file,将替换的结果写到文件中
#查看data5数据
$ cat data5
This is a test of the test script.
This is a the second test of the test script.
#替换每行第二个匹配的字符串
$ sed 's/test/trial/2' data5
This is a test of the trial script.
This is a the second test of the trial script.
#g替换标记可以替换文本中所有匹配的字符串
$ sed 's/test/trial/g' data5
This is a trial of the trial script.
This is a the second trial of the trial script.
#p替换标记会打印包含与subsitute命令中指定的模式匹配的行。这通常和-n选项一起使用
$ cat data6
This is a test line.
This is a different line.
$
$ sed -n 's/test/trial/p' data6
This is a trial line.
#-n选项将禁止sed编辑器输出。但p替换标记会输出修改过的行。将二者配合使用则会只输出被substitute命令修改过的行。
#w替换标记会产生同样的输出,不过会将输出保存到指定文件中:
$ sed 's/test/trial/w test' data6
This is a trial line.
This is a different line.##这里没有-n所以会输出所有行
$
$ cat test
This is a trial line.
$

sed编辑器的正常输出是在STDOUT中,而只有那些包含匹配模式的行才会保存在指定的输出文件中。

2、替换字符
有时会遇到一些文本字符串中的字符不方便在替换模式中使用的情况。Linux中一个流行的例子是正斜线。
替换文件中的路径名会比较麻烦。比如,想用c shell替换/etc/passwd
文件中的bash shell,必须要这么做:

#正斜线通常用作字符串分隔符,如果它出现在了模式文本中的话,
#必须用反斜线转义。这通常会带来一些困惑和错误。
$ sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd

为了解决这个问题,sed编辑器允许选择其他字符来作为substitue命令中的字符串分隔符:

$ sed 's!/bin/bash!/bin/csh!' /etc/passwd
#这里用感叹号作字符串分隔符,使得路径名很容易被读取和理解。

3、使用地址
默认情况下,在sed编辑器中使用的命令会作用于文本数据的所有行。如果只想将命令作用于特定某行或某些行,必须使用行寻址line addressing。
sed编辑器中有两种形式的行寻址:
1. 行的数字范围
2. 用文本模式来过滤出某行

两种形式都使用相同的格式来指定地址

[address]command

也可以为特定地址将多个命令放在一起:

address{
    command1
    command2
}

sed编辑器会将指定的每条命令只作用到匹配指定地址的行上。
1. 数字方式的行寻址
使用数字方式的行寻址时可以用它们在文本流中的行位置来引用行。在命令中指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定一定范围内的行。

#修改指定行
$ sed '2s/dog/cat/' data1
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

#修改一定范围内的行
$ sed '2,3s/dog/cat/' data1
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog

#如果希望命令作用到文本的结尾行,可以用特殊地址——美元符
$ sed '2,$s/dog/cat/' data1
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat

2.使用文本模式过滤器
sed编辑器允许指定文本模式来过滤出命令要作用的行。格式如下:

/pattern/command

该命令只作用到匹配文本模式的行上。虽然使用固定文本模式能帮你过滤出特定的值,但这样做通常有些局限,sed编辑器在文本模式中会采用一种称为正则表达式的特性来帮助创建更能很好的匹配的模式。

3.组合命令
如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起,sed编辑器会处理列在地址行的每条命令:

$ sed '2{
> s/fox/elephant/
> s/dog/cat/
> }' data1
The quick brown fox jumps over the lazy dog.
The quick brown elephant jumps over the lazy cat.
The quick brown fox jumps over the lazy dog.
The quick brown fox jumps over the lazy dog.
$

这样会让两条命令都作用到该地址上。当然,也可以在一组命令前指定一个地址范围:

$ sed '3,${
>s/brown/green/
>s/lazy/active/
>}' data1

sed编辑器会将所有命令作用到该地址范围内的所有行上。
4. 删除行
如果要删除文本流中的特定行,可以用删除delete命令。

#删除data1文件的所有行
$sed 'd' data1
#删除文件的指定行
$sed '3d' data7 #删除data7的第三行
#删除文件的指定多行
$sed '3,$d' data7 #删除data7的第三行到结尾行
#将模式匹配应用于删除命令
$sed '/number 1/d' data7 #删除含number 1字段的行

注意:sed编辑器不会修改原始文件。删除的行只是从sed编辑器的输出中消失了。原始文件仍然包含那些“删掉”行。

也可以用两个文本模式来删除某个范围内的行,但是这么做要小心。指定的第一个模式会“打开”行删除功能,第二个模式会“关闭”行删除功能。sed编辑器会删除两个指定行之间的所有行。

$ cat data8
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
This is line number 1 again.
This is text you want to keep.
This is the last lien in the file.
$ 
$ sed '/1/./3/d' data8
This is line number 4.
$

第二个出现数字“1”的行再次触发了删除命令,删除了数据流中的剩余行,因为停止模式没找到。如果指定了一个停止模式没有匹配的文本行,那么会删除开始行之后的所有文本。

$ sed '/1/./5/d' data8
$
#因为删除功能在匹配到一个模式的时候打开了,但一直没匹配到结束模式。
#所以整个数据流都被删掉了。

5. 插入和附加文本
sed编辑器允许向数据流插入和附加文本行。两个操作是i和a:
1. 插入insert命令i会在指定行前增加一个新行
2. 追加append命令a会在指定行后增加一个新行

# 插入命令,文本出现在数据流文本的前面
$ echo "Test Line 2" | sed 'i\Test Line 1'
Test Line 1
Test Line 2
$
#附加命令,文本出现在数据流文本的后面
$ echo "Test Line 2" | sed 'a\Test Line 1'
Test Line 2
Test Line 1
$

要给数据流行中插入和附加数据,必须用寻址来告诉sed编辑器让数据出现在什么位置。你可以在用这些命令时只指定一个行地址。可以匹配一个数字行号或文本模式,但不能用地址区间。因为你只能将文本插入或附加到单个行的前面或后面,而不能是行区间的前面或后面。

要插入或附加多行文本,你必须对新文本中的每一行使用反斜线,直到要插入或附加的文本的最后一行。

$ sed '1i\
> This is one line of new text.\
> This is another line of new text.' data7
This is one line of new text.
This is another line of new text.
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.

6. 修改行
修改命令允许修改数据流中整行文本的内容。

#修改第三行
$ sed '3c\
> This is a changed line of text.' data7
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
$
#用文本模式寻址后修改
$ sed '/number 3/c\
> This is a changed line of text.' data7
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
#也可以在修改命令中使用地址区间,但是会将原来地址区间的所有行
#替换成新行
$ sed '2,3c\
>This is a new line of text.' data7
This is line number 1.
This is a new line of text.
This is line number 4.
$

7. 转换命令
转换y命令是唯一可以处理单个字符的sed编辑器命令。
[address]y/inchars/outchars/
转换命令会进行inchars和outchars值的一对一映射。inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换为outchars的第二个字符。这个映射会一直持续到处理完指定字符。如果inchars和outchars长度不同,则sed编辑器会产生一条错误消息。

$ cat data8
This is line number 1.
This is line number 2.
This is line number 3.
This is new line number 11.
$ sed 'y/123/789/' data8
This is line number 7.
This is line number 8.
This is line number 9.
This is new line number 77.

注:转换命令是一个全局命令,它会自动替换文本行中找到的指定字符的所有实例,而不会考虑他们出现的位置。你不能限定只更改该字符出现的特定的某个地方。

8. 打印命令补充
还有三个命令来打印数据流中的信息:
1. 小写p命令用来打印文本行
2. 等号=命令用来打印行号
3. l命令用来列出行

1) p命令
跟替换命令中的p标记类似,p命令可以打印sed编辑器输出中的一行。如果只用这个命令也没特别的。它最常见的用法是打印包含匹配文本模式的行:

#在命令行上用-n选项,就能禁止其他行,只打印包含匹配文本模式的行
$ sed -n '/number 3/p' data7
This is line number 3.
$
#打印修改前后的文本行
$ sed -n '/3/{
p
s/line/test/p
}' data7
This is line number 3.
This is test number 3.
$
#脚本用p命令来打印出该行原来的版本,然后用s命令替换文本,并用p标记打印出了最终文本。输出同时显示了原来的行文本和新的行文本。

2) 打印行号
等号命令会打印行在数据流中的当前行号。行号由数据流中的换行符决定。

$ sed '=' data1
1
The quick brown fox jumps over the lazy dog
2
The quick brown fox jumps over the lazy dog
3
The quick brown fox jumps over the lazy dog
4
The quick brown fox jumps over the lazy dog
$

如果要在数据流中查找特定文本模式,等号也能派上用场。

$ sed -n '/number 4/{
=
p
}'data7
4
This is line number 4
$

3) 列出列
列出命令l允许打印数据流中的文本和不可打印的ASCII字符。任何不可打印字符都用它们的八进制值前加一个反斜线或标准c风格的命名法(用于常见的不可打印字符),比如\t来代表制表符:

#data9文本文件包含了转义控制码来改变显示的颜色,用cat命令来显示文本文件时,不会看到转义控制码,只会改变显示的颜色。\033是Esc键对应的八进制ASCII码。
$ cat data9
This is a test
$
$ sed -n 'l' data9
This is a test \033[44m$
$
3.3 用sed和文件一起工作

1. 向文件写入
命令格式如下:

[address]w filename
#filename可以是相对或绝对路径名,运行sed编辑器的人都必须有文件的写权限。

地址可以是sed中支持的任意类型的寻址方法,例如单个行号、文本模式或者一系列行号或文本模式。

$ sed '1,2w test' data7
This is line number 1
This is line number 2
This is line number 3
This is line number 4
$
$ cat test
This is line number 1
This is line number 2

也可以将只包含文本模式的数据行写入目标文件。

2. 从文件读取数据
读取命令r允许将一个独立文件中的数据插入到数据流中。
读取命令的格式:

[address]r filename

filename参数指定数据文件的绝对和相对路径名。不能对读取命令使用地址区间,而只能指定单独一个行号或文本模式地址。

$ cat data10
This is an added line
This is the second added line
$
$ sed '3r data10' data7
This is line number 1
This is line number 2
This is line number 3
This is an added line
This is the second added line
This is line number 4
$

如果你要在数据流的末尾添加文本,只要用美元符地址符就行了。

$ sed '$r data10' data7
This is line number 1
This is line number 2
This is line number 3
This is line number 4
This is an added line
This is the second added line

读取命令的另一个很好的用途是将它和删除命令一起使用来用另一文件中的数据替换文件中的占位文本。

$ cat Letter
would the following people:
LIST
please report to the office.
$
$ cat name
kate lina
Tina
$ sed '/LIST/{
>r name
>d
>}' letter
would the following people:
kate lina
Tina
please report to the office.
#占位文本LIST替换成文件name中的名单
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值