二、sed编辑器基础
2.sed编辑器基础
sed命令 | 作用 | 作用范围 | 示例 |
---|---|---|---|
s | 替换 | 行内 | sed 's/test/trial/' data4.txt |
d | 删除 | 整行 | sed '3d' data6.txt |
a | 增加 | 整行 | sed '3i\This is an inserted line.' data6.txt |
i | 插入 | 整行 | sed '3a\This is an inserted line.' data6.txt |
c | 修改 | 整行 | sed '3c\This is a changed line of text.' data6.txt |
y | 转换 | 单个字符 | sed 'y/123/789/' data8.txt |
一、更多的替换选项
1.替换标记(字符串)
[root@elk test]# cat data4.txt
This is a test of the test script.
This is the second test of the test script.
[root@elk test]# sed 's/test/trial/' data4.txt
This is a trial of the test script.
This is the second trial of the test script.
使用s命令(substitute)来在行中替换文本,默认情况下它只替换每行中出现的第一处。要让替换命令能够替换一行中不同地方出现的文本必须使用替换标记(substitution flag)。替换标记会在替换命令字符串之后设置。
s/pattern/replacement/flags
有4种可用的替换标记:
- 数字,表明新文本将替换第几处模式匹配的地方;
- g,表明新文本将替换所有匹配的文本;
- p,表明原先行的内容要打印出来;
- w file,将替换的结果写入到文件中。
示例:
替换第二处匹配到的文本
[root@elk test]# sed 's/test/trial/2' data4.txt
This is a test of the trial script.
This is the second test of the trial script.
替换所有匹配到的文本
[root@elk test]# sed 's/test/trial/g' data4.txt
This is a trial of the trial script.
This is the second trial of the trial script.
p替换标记会打印与替换命令中指定的模式匹配的行。这通常会和sed的-n选项一起使用(-n选项将禁止sed编辑器输出,但p替换标记会输出修改过的行,将二者配合使用的效果就是只输出被替换命令修改过的行。)
[root@elk test]# cat data5.txt
This is a test line.
This is a different line.
[root@elk test]# sed -n 's/test/trial/p' data5.txt
This is a trial line.
w替换标记会产生同样的输出,不过会将包含匹配模式的行输出保存到指定文件中。
[root@elk test]# sed 's/test/trial/w test.txt' data5.txt
This is a trial line.
This is a different line.
[root@elk test]# cat test.txt
This is a trial line.
2.替换字符
在文本字符串中会遇到正斜杠(/)类型的字符,例如在替换文件中路径名时会比较麻烦,需要做转义。
[root@elk test]# sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/csh
省略......
elasticsearch:x:1000:1000::/home/elasticsearch:/bin/csh
sed编辑器允许选择其他字符来作为替换命令中的字符串分隔符:
[root@elk test]# sed 's!/bin/bash!/bin/csh!' /etc/passwd
上面的例子中使用感叹号( ! )作为字符串分隔符,这样路径名就更容易阅读和理解了。
二、使用地址(让sed作用于特定行)
默认情况下,sed编辑器中使用的命令会作用于文本数据的所有行。如果只想将命令作用于特定行或某些行,则必须用行寻址(line addressing)
在sed编辑器中有两种形式的行寻址:
- 以数字形式标示行区间
- 用文本模式来过滤出行
这两种形式都使用相同的格式来指定地址:
[address] command
也可以将特定地址的多个命令分组:
address {
command1
command2
command3
}
sed编辑器会将指定的每条命令作用到匹配指定地址的行上。
1.数字方式的行寻址
在命令中指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。
指定单行
[root@elk test]# cat data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
[root@elk test]# sed '2s/dog/cat/' data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
指定行地址区间
[root@elk test]# sed '2,3s/dog/cat/' data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy dog.
从某行开始到结尾,使用美元符($)
[root@elk test]# sed '2,$s/dog/cat/' data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy cat.
2.使用文本模式过滤器
sed编辑器允许指定文本模式来过滤出命令要作用的行。
/pattern/command
必须用正斜线将要指定的pattern封起来。
例如,只想修改用户elasticsearch的默认shell:
[root@elk test]# grep elasticsearch /etc/passwd
elasticsearch:x:1000:1000::/home/elasticsearch:/bin/bash
[root@elk test]# sed '/elasticsearch/s/bash/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
省略......
elasticsearch:x:1000:1000::/home/elasticsearch:/bin/csh
只输出替换过的行
[root@elk test]# sed -n '/elasticsearch/s/bash/csh/p' /etc/passwd
elasticsearch:x:1000:1000::/home/elasticsearch:/bin/csh
局限性:虽然使用文本过滤器能过滤出特定的行,但作用难免有限。可以采用正则表达式来获得更好的效果。
3.命令自核
如果需要在单行上执行多条命令,可以用花括号将多条命令组合在一起。
[root@elk test]# sed '2{
> s/fox/elephant/
> s/dog/cat/
> }' data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy cat.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
也可以指定一个地址区间。
[root@elk test]# sed '3,${
> s/brown/green/
> s/lazy/active/
> }' data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the active dog.
The quick green elephant jumps over the active dog.
三、删除行
命令d,删除匹配指定寻址模式的所有行。
[root@elk test]# cat data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
[root@elk test]# sed 'd' data1.txt
没有加寻址模式的话,流中的所有文本都会被删除。
[root@elk test]# cat data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
[root@elk test]# sed '3d' data6.txt
This is line number 1.
This is line number 2.
This is line number 4.
[root@elk test]# sed '2,3d' data6.txt
This is line number 1.
This is line number 4.
[root@elk test]# sed '3,$d' data6.txt
This is line number 1.
This is line number 2.
[root@elk test]# sed '/number 1/d' data6.txt
This is line number 2.
This is line number 3.
This is line number 4.
使用两个文本模式来删除某个区间内的行。
[root@elk test]# sed '/number 1/,/number 3/d' data6.txt
This is line number 4.
指定的第一个模式会“打开”行删除功能,第二个模式会“关闭”行删除功能,特别要注意“打开”后需要”关闭“不然会出现不期望的结果。
四、插入和附加文本
- 插入(insert)命令( i )会在指定行前增加一个新行;
- 附加(append)命令( a )会在指定行后增加一个新行。
上面两个命令不能在单个命令行上使用,必须指定是要将行插入还是附加到另一行。
格式:
sed '[address] command\new line'
new line中的文本将会出现在sed编辑器输出中你指定的位置。
插入
[root@elk test]# echo "Test Line 2" | sed 'i\Test Line 1'
Test Line 1
Test Line 2
附加
[root@elk test]# echo "Test Line 2" | sed 'a\Test Line 1'
Test Line 2
Test Line 1
也可以匹配一个数字行号或文本模式,但不能用地址区间。
[root@elk test]# sed '3i\
> This is an inserted line.' data6.txt
This is line number 1.
This is line number 2.
This is an inserted line.
This is line number 3.
This is line number 4.
将新行附加到数据流末尾,使用代表最后一行的$符号
[root@elk test]# sed '$a\
This is a new line of text' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
This is a new line of text
一次插入多行,在新文本后使用反斜线。
[root@elk test]# sed '1i\
> This is one line of new text.\
> This is another line of new text.
> ' data6.txt
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.
五、修改行
修改(change)命令,允许修改数据流中的整行文本内容。他和插入附加命令工作机制一样,必须在sed命令中单独指定修改的行。
[root@elk test]# sed '3c\This is a changed line of text.' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
使用文本模式来寻址
[root@elk test]# sed '/number 3/c\
> This is a changed line of text.' data6.txt
This is line number 1.
This is line number 2.
This is a changed line of text.
This is line number 4.
文本模式会修改匹配到的所有行
[root@elk test]# cat data8.txt
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 yet anoter line.
This is the last line in the file.
[root@elk test]# sed '/number 1/c\
> This is a changed line of text.' data8.txt
This is a changed line of text.
This is line number 2.
This is line number 3.
This is line number 4.
This is a changed line of text.
This is yet anoter line.
This is the last line in the file.
使用地址区间,不是逐行修改
[root@elk test]# sed '2,3c\
> This is a new line of text.' data6.txt
This is line number 1.
This is a new line of text.
This is line number 4.
六、转换命令
转换(transform)命令( y )是唯一可以处理单个字符的sed编辑器命令。
命令格式:
[address]y/inchars/outchars/
转换命令会对inchars和outchars值进行一对一的映射。inchars中的第一个字符会被转换为outchars中的第一个字符,第二个字符会被转换成outchars中的第二个字符。这个映射过程会一直持续到处理完指定字符。如果inchars和outchars的长度不同,则sed编辑器会产生一条错误消息。
[root@elk test]# sed 'y/123/789/' data8.txt
This is line number 7.
This is line number 8.
This is line number 9.
This is line number 4.
This is line number 7 again.
This is yet anoter line.
This is the last line in the file.
可以使用寻址,和文本模式过滤。
转换命令是一个全局命令,文本中找到的所有指定字符都会进行转换。而不用考虑它们出现的位置。
[root@elk test]# echo "This 1 is a test of 1 try." | sed 'y/123/456/'
This 4 is a test of 4 try.
无法限定只转换在特定地方出现的字符。
七、回顾打印
前面介绍过使用p命令可以显示sed编辑器修改过的行。另外有3个命令也可以用来打印数据流中的信息:
- p命令用来打印文本行;
- 等号( = )命令用来打印行号;
- l(小写的 L)命令用来列出行。
1.打印行
跟替换命令中的p标记类似,p命令可以打印sed编辑器输出中的一行。如果只用这个命令没有什么特别的。
[root@elk test]# echo "this is a test" | sed 'p'
this is a test
this is a test
配合-n选项,只打印包含匹配模式的行。
[root@elk test]# cat data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
[root@elk test]# sed -n '/number 3/p' data6.txt
This is line number 3.
也可以用来快速打印数据流中的某些行。
[root@elk test]# sed -n '2,3p' data6.txt
This is line number 2.
This is line number 3.
回顾打印修改前和修改后的行。
[root@elk test]# sed -n '/number 3/{
> p
> s/line/test/p
> }' data6.txt
This is line number 3.
This is test number 3.
说明:先使用-n不产生输出,再通过文本过滤出第三行,大括号中写多行命令;p先打印原始行,再替换关键词且打印,最后输出原始行和修改后的行。
2.打印行号
等于号( = )会打印行号,每次输出会换行。
[root@elk test]# cat data1.txt
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
The quick green elephant jumps over the lazy dog.
[root@elk test]# sed '=' data1.txt
1
The quick green elephant jumps over the lazy dog.
2
The quick green elephant jumps over the lazy dog.
3
The quick green elephant jumps over the lazy dog.
4
The quick green elephant jumps over the lazy dog.
3.列出行
列出(list)命令( l )可以打印数据流中的文本和不可打印的ASCII字符。任何不可打印字符要么在其八进制值前加一个反斜线,要么使用标准C风格的命名法(用于常见的不可打印字符),比如 \t ,来代表制表符。
[root@elk test]# cat data9.txt
This line contains tabs.
[root@elk test]# sed -n 'l' data9.txt
This\tline\tcontains\t\ttabs.$
制表符的位置使用 \t 来显示。行尾的美元符号表示换行符。如果数据流包含了转义字符,列出命令会在必要时候用八进制码来显示。
八、使用sed处理文件
1.写入文件
w命令用来向文件写入行。该命令格式如下:
[address]w filename
filename可以使用相对路径或绝对路径,只需要用户对文件具有写权限。地址可以是sed中支持的任意类型寻址方式,例如单个行号、行区间、文本模式。
将数据流中的前两行打印到一个文本文件中。
[root@elk test]# sed '1,2w test.txt' data6.txt
This is line number 1.
This is line number 2.
This is line number 3.
This is line number 4.
[root@elk test]# cat test.txt
This is line number 1.
This is line number 2.
打印写入的行信息
[root@elk test]# sed -n '3,4{
p
w test.txt
}' data6.txt
This is line number 3.
This is line number 4.
[root@elk test]# cat test.txt
This is line number 3.
This is line number 4.
2.从文件读取数据
前面已经了解了如何在sed命令行上向数据流中插入( i )或附加( a )文本。读取( read )命令( r )允许你将一个独立文件中的数据插入到数据流中。
读取命令格式如下:
[address]r filename
filename参数指定了数据文本的绝对路径或相对路径。你在读取命令中使用地址区间,只能指定单独一个行号或文本模式地址。sed编辑器会将文件中的内容插入到指定地址后。
[root@elk test]# cat data12.txt
This is an added line.
This is the second added line.
[root@elk test]# sed '3r data12.txt' data6.txt
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.
同样使用文本模式地址时也是一样的,如果你要在数据流的末尾添加文本,只需要用美元符( $ )地址符号就可以了。
搭配删除命令,利用另一个文件中的数据来替换文件中的占位文本。
例如:
please report to the ship's captain.
[root@elk test]# cat data11.txt
Blum, R Browncoat
McGuiness, A Alliance
Bresnahan, C Browncoat
Harken, C Alliance
[root@elk test]# cat notice.std
Would the following people:
LIST
please report to the ship's captain.
[root@elk test]# sed '/LIST/{
> r data11.txt
> d
> }' notice.std
Would the following people:
Blum, R Browncoat
McGuiness, A Alliance
Bresnahan, C Browncoat
Harken, C Alliance
please report to the ship's captain.