sed
调用方式
sed [-n] program [file-list] sed [-n] -f program-file [file-list]
常用参数:
-
--file program-file
或-f program-file
-
--in-place[=suffix]
或-i[suffix]
:不输出到标准输出,而是修改源文件。 有[suffix]
时会生成指定suffix
后缀的备份文件。 -
--quiet
或--silent
或-n
:除非程序中指定调用print
或p
命令, 不然不输出内容。
也可以作为脚本调用,例如下面的程序清理每一行行尾的空格:
$ cat cleanup #!/bin/sed -f s/ *$//
sed程序的格式为,读取文本的每一行,对全匹配到模式的那一行执行对应的指令:
[模式[, 模式]] 指令 [指令相关的参数列表]
同一行文本可能被多个匹配到的模式处理。
例:打印出包含字符串line
的那一行:
$ cat new Line one. The second line. The third. This is line four. Five. This is the sixth sentence. This is line seven. Eighth and last. $ sed '/line/ p' new Line one. The second line. The second line. The third. This is line four. This is line four. Five. This is the sixth sentence. This is line seven. This is line seven. Eighth and last.
例:参数-n
设置不回显读到的每一行:
$ sed -n '/line/ p' new The second line. This is line four. This is line seven.
基本概念
行号
$ sed -n '3,6 p' new The third. This is line four. Five. This is the sixth sentence.
控制结构
NOT
与!
表示排除操作:
$ sed -n '2, 4! p' new Line one. Five. This is the sixth sentence. This is line seven. Eighth and last.
花括号{}
组合多条语句。对于匹配到的一个模式,用花括号可以组合多个操作。
Pattern区和Hold区
Pattern区是命令直接编辑的缓存区域,保存着sed刚刚从输入中读取的行; Hold区是用来暂存数据的临时缓冲区,在把数据放入Hold区之前内容为空。
在Pattern区与Hold区之间进行数据传送的命令:
-
g
:Hold的内容移动并覆盖Pattern中所有的内容。 -
G
:把一个换行符和Hold的内容追加到Pattern原来内容之后。 -
h
:Pattern的内容移动并覆盖Hold中所有的内容。 -
H
:把一个换行符和Pattern的内容追加到Hold原来内容之后。 -
x
:交换Pattern和Hold中的内容。
例:通过在Hold区与Pattern区交换内容,实现文本的内容两两交换:
$ cat switchline # 把文件中的文本每两行两两交换 h # 把刚刚读到的一行从Pattern复制到Hold n # 把下一行读到Pattern p # 打印Pattern的内容 g # 把Hold中的内容复制到Pattern p # 打印Pattern的内容 $ sed -nf switchline new The second line. Line one. This is line four. The third. This is the sixth sentence. Five. Eighth and last. This is line seven.
例:G
命令在复制的时候还会增加一个换行:
$ sed 'G' new Line one. The second line. The third. This is line four. Five. This is the sixth sentence. This is line seven. Eighth and last.
例子,反转所有的行:
$ cat desc 2,$ G # 除了第一行外的每一行,都要添加到Pattern原来的内容后面 h # Pattern覆盖到Hold $! d # 删除除了最后一行的所有行 $ sed -f desc new Eighth and last. This is line seven. This is the sixth sentence. Five. This is line four. The third. The second line. Line one.
$
表示最后一行,
$!
表示最后一行外的所有行。
Pattern | Hold | |
---|---|---|
第1行读到Pattern | 第1行 | |
2,$ G 不包含第一行
|
第1行 | |
h 从Pattern覆盖到Hold
|
第1行 | 第1行 |
$! G 清空Pattern
|
第1行 | |
第2行读到Pattern | 第2行 | 第1行 |
2,$ G 追加Hold到Pattern
|
第2行 第1行 | 第1行 |
h 从Pattern覆盖到Hold
|
第2行 第1行 | 第2行 第1行 |
$! G 清空Pattern
|
第2行 第1行 | |
第3行读到Pattern | 第3行 | 第2行 第1行 |
2,$ G 追加Hold到Pattern
|
第3行 第2行 第1行 | 第2行 第1行 |
h 从Pattern覆盖到Hold
|
第3行 第2行 第1行 | 第3行 第2行 第1行 |
$! G 清空Pattern
|
第3行 第2行 第1行 | |
....... | ....... | ....... |
第8行读到Pattern | 第8行 | 第7行 ... 第1行 |
2,$ G 追加Hold到Pattern
|
第8行 第7行 ... 第1行 | 第7行 ... 第1行 |
h 从Pattern覆盖到Hold
|
第8行 第7行 ... 第1行 | 第8行 第7行 ... 第1行 |
$! G 最后一行不执行
|
第8行 第7行 ... 第1行 | 第8行 第7行 ... 第1行 |
常用指令
打印指令p
$ sed '/line/ p' new Line one. The second line. The second line. The third. This is line four. This is line four. Five. This is the sixth sentence. This is line seven. This is line seven. Eighth and last.
退出指令q
读到第五行就退出程序
$ sed '5 q' new Line one. The second line. The third. This is line four. Five.
后面添加文本指令a
在第二行后添加新行,内容为【AFTER】:
$ sed '2 a AFTER.' new Line one. The second line. AFTER. The third. This is line four. Five. This is the sixth sentence. This is line seven. Eighth and last.
前面添加文本指令i
模式【This】前添加新行,内容为【BEFORE】:
$ sed '/This/ i BEFORE.' new Line one. The second line. The third. BEFORE. This is line four. Five. BEFORE. This is the sixth sentence. BEFORE. This is line seven. Eighth and last.
文本修改指令change
$ sed '/second/ c 2nd' new Line one. 2nd The third. This is line four. Five. This is the sixth sentence. This is line seven. Eighth and last.
如果用行号指定范围,替换的不是每一行,而是所有行作为一个整体替换:
$ sed '2,4 c\ lin1\ lin2\ lin3' new Line one. lin1 lin2 lin3 Five. This is the sixth sentence. This is line seven. Eighth and last.
正则表达式替换substitute
正则表达式标志p
表示替换后的每一行都要打印出来:
$ sed -n 's/line/sentence/p' new The second sentence. This is sentence four. This is sentence seven.
正则表达式标志w
指定输出到文件temp
:
$ sed -n 's/line/sentence/w temp' new $ cat temp The second sentence. This is sentence four. This is sentence seven.
正则表达式标志g
表示同一行中出现的多个匹配都会被替换:
$ sed -n 's/line/sentence/g' new
例子:修改多个文件内容的脚本:
$ cat sub #!/bin/bash for file do echo $file mv $file $$.subhld sed 's/REPORT/report/g s/FILE/file/g s/PROCESS/process/g' $$.subhld > $file done rm $$.subhld $ bash ./sub file1 file2 file3 file1 file2 file3 $ cat file* report file process report file process report file process
正则表达式替换时,符号'&'代表匹配到的内容:
$ cat example.properties username= password= $ sed -n 's/username=/&password/p s/password=/&p@ssw0rd/p' example.properties username=password password=p@ssw0rd
写入到文件指令write
$ sed -n '2,4 w temp2' new $ cat temp2 The second line. The third. This is line four.
跳过一行的指令next
$ sed -n '/the/ n p' new Line one. The second line. The third. This is line four. Five. This is line seven. Eighth and last.
例子
替换文件中的引号
Unicode 序列u2018
和u2019
产生‘
和’
,
而代码u201c
和u201d
产生“
和”
字符:
#!/bin/sh # GNU All-Permissive License SDQUO=$(echo -ne '\u2018\u2019') RDQUO=$(echo -ne '\u201C\u201D') $SED -i -e "s/[$SDQUO]/\'/g" -e "s/[$RDQUO]/\"/g" "${1}"
调用的例子;
$ cat test.txt ‘Single quote’ “Double quote” $ bash ./fixquotes.sh test.txt $ cat test.txt 'Single quote' "Double quote"
修改远程文件
#!/usr/bin/expect -f if { $argc != 6 } { send_user "usage: expect change-config-sample.exp hostname portnum uname password filename value1 value2 \n" exit } #define var set timeout 30 set hostname [lindex $argv 0] set portnum [lindex $argv 1] set uname [lindex $argv 2] set password [lindex $argv 3] set filename [lindex $argv 4] set value1 [lindex $argv 5] set value2 [lindex $argv 6] set cmd01 " sed -i 's/key1=.*$/key1=${value1}/' ${filename} \n" set cmd02 " sed -i 's/key2=.*$/key1=${value2}/' ${filename} " set cmd99 " echo -e \" ${cmd01} ${cmd02} \" | bash " set cmdstr " ${cmd99} && sync && reboot " spawn ssh ${uname}@${hostname} -p ${portnum} ${cmdstr} expect { "yes/no" { send "yes\r"; exp_continue } "*password:" { exp_send "${password}\r" } timeout { puts "expect connect timeout,pls contact xp"; return; } } expect eof exit
调用方式:
expect change-clientcode-on-linux.exp "127.0.0.1" 22 "root" "password" \ "/etc/myapp/cfg.properties" "value1" "value2" ; \ sleep 1; read -p "Press enter to continue";