shell编程,sed编辑器的使用及常用命令
sed编辑器常用操作符:
s 替换
d 删除
i 插入
a 追加
c 修改
y 粘贴
p 打印
= 打印行号
l 列表
w 写入
r 读取
g 替换所有
q 退出
n 当前行的下一行
D 删除模式空间的第一行
G 加倍行间距
N 下一行添加到模式空间
P 只打印模式空间的第一行
t 分支
使用格式:
[address]操作符command
sed编辑器使用格式:
sed options script file
-e 使用多个编辑器命令
-f 指定文件编辑器命令
-n 表示禁止输出,使用print命令来完成输出
-i 修改原文件,直接编辑原文件,且修改后无法还原
例1:echo "This is a test" | sed 's/test/big test/' 替换字符串,test替换为big test
例2:sed 's/dog/cat/' data.txt 替换文件中的字符
多个替换命令:
例:sed -e 's/brown/green/; s/god/cat/' data.txt 使用多个编辑命令
注意:几个命令都是在单引号之内的。
命令写入脚本:
cat script.sed
s/brown/green/
s/god/cat/
s/fox/elephant/
sed -f script.sed data.txt 使用script.sed文件中的命令处理data.txt文件的内容
替换标记:
s/pattern/replacement/flags
flags 当flags为数字时,这个数字代表要替换掉匹配到的第几个字符串
g 替换所有匹配到的字符串
p 输出修改过的行,与-n一起使用表示只输出修改过的行,-n表示禁止输出
w 将替换结果写到文件中
替换匹配到的第n个字符:
cat demo.txt
1 This is a test This is a test
2 This is a test This is a test
sed 's/test/apple/2' demo.txt 这个2表示某行中替换匹配到的第二个test
1 This is a test This is a apple
2 This is a test This is a apple
替换结果写入文件:
例:sed 's/test/apple/w save-data.txt' demo.txt 会将修改过的行输出到data.txt中
注意单引号将输出的文件名也包括在内
字符串分隔符:
可以自定义字符串分隔符
例1:sed 's/\/bin\/bash/\/bin\/csh/' /etc/passwd 一般的分隔符
例2:sed 's!/bin/bash!/bin/csh!' /etc/passwd 自定义分隔符
数字寻址:
单条命令格式:[address]command
多条命令格式:[address]{
command1
command2
}
部分匹配寻址:
sed '2s/dog/cat/' data.txt 只替换第二行的dog
sed '2,3s/dog/cat/' data.txt 替换2到3行的dog
sed '2,s/dog/cat/' data.txt 替换第2行之后的所有dog
文本匹配寻址:sed '/hello/s/dog/cat/' data.txt 匹配到含有hello的行,将dog替换成cat
同时执行多条命令:
sed '2{
s/dog/cat/
s/fox/dog/
}' data.txt
将data.txt中第二行的dog和fox替换成对应的单词
sed 'd' data.txt 删除所有行
sed '3,d' data.txt 删除第三行
sed '3,$' data.txt 从第三行删除到最后
sed '3,5' data.txt 删除3到5行
sed '/world/d' data.txt 删除包含world的行
sed '/start/,/end/d' data.txt 删除包含start的字符到包含end的字符之间的所有行,如果文件中有两段这样模式的字符会删除两次,如果未找到结束的end字符,则剩下的全部删除。
插入和附加文本到数据流:
[address]command\ 使用格式
将line 1插入到line2的前面 insert,反斜线不加也可
echo 'hello' | sed 'i\world' world hello
将line 1添加到line 2的后面 append
echo 'hello' | sed 'a\world' hello world
将new line插入到数据流的第三行,输出如下:
sed '3i\This is new line' data.txt This is line number 1. This is line number 2. This is new line This is line number 3.
使用$符号将数据添加到行尾
sed '$a\new line' data.txt
将这两行添加到数据流的第一行
sed '1i\ >new line 1\ #换行使用反斜杠“\” >new line 2' data.txt
在文件中指定位置追加:
sed -i '/ExecStart=/a\ExecStartPost=/usr/sbin/iptables -P FORWARD ACCEPT' /usr/lib/systemd/system/docker.service
修改行:
[address]command\
例1:sed '3c\new worlds' data.txt 将数据流的第三行修改为new worlds
例2:sed '/dog/c\ cat' data.txt 将数据流中匹配到的dog行全部修改为cat
例3:sed '2,5c\dog\cat' data.txt 将2到5行的数据替换为新的数据
转换命令/单字符替换:
y 单字符一对一替换,使用格式[address]y/inchars/outchars/
例:sed 'y/ab/cd/' data.txt 将全部数据流中的a替换成c,b替换成d,如果要替换的字符长度不对应会报错,只能指定行到行之间替换,无法指定某一行的单独位置替换。
打印行:
例1:echo "This is a test" | sed 'p' 将输出的打印
例2:sed -n '/hello/p' data.txt 打印出匹配到的
例3:sed -n '2,3p' data.txt 只打印出指定的行
例4:
sed -n '/hello/{ #匹配到有hello的行
>p #先显示修改之前的
>s/hello/world/p #再显示出修改之后的
}' data.txt
打印行号:
例:sed '=' data.txt
例:
sed -n '/three/{
= #打印行号
p #打印查找到的行
}' data.txt
列出行:
例:sed -n 'l' data.txt
数据写入文件:
[address]w filename
例:
sed '2,5w demo.txt' data.txt 将data.txt中的第2到5行写入demo.txt文件中
sed -n '/hello/w demo.txt' data.txt 将包含有hello的行写入demo.txt中
从文件中读取数据:
[address]r filename
例1:sed '3r demo.txt' data.txt 将demo.txt中的文本插入到数据流的第3行
例2:sed '/hello/r demo.txt' data.txt 将demo.txt中的数据插入到数据流的hello字符后面
例3:sed '$r demo.txt' data.txt 将demo.txt中的数据插入到数据流的最后
例4:将文件添加到占位符的位置,并删除占位符
数据流中的文件:
cat data.txt
Would the following people:
LIST
please report tp the ship's captain.
列表文件:
cat list.txt
Hello
world
将列表替换原来的LIST占位符:
sed '/LIST/{
r list.txt
d
}' data.txt
替换的结果为:
Would the following people:
Hello
world
please report tp the ship's captain
next命令:
例:sed '/hello/{n ; d}' data.txt 找到当前行的下一行,并删除,n命令会指向下一行,d命令执行删除
合并文本行:
sed '
>s/System Adminstrator/Desktop User/ #替换单行的情况
>N
>s/System\nAdminstrator/Desktop\nUser/ #替换句子分布在多行的情况
' data.txt
多行删除命令:
sed 'N ; /hello\nworld/D' data.txt 匹配到hello world的两行,再删除包含有hello的行
sed '/^$/{N ; /header/D}' data.txt 删除header行上一行的空白
多行打印命令:
sed -n 'N ; /hello\nworld/P' data.txt
保持空间:
sed编辑器有两个缓冲区,模式空间和保持空间
操作保持空间的命令
h 将模式空间复制到保持空间
H 将模式空间附加到保持空间
g 将保持空间复制到模式空间
G 将保持空间附加到模式空间
x 交换模式空间和保持空间的内容
排除命令:
! 不执行匹配的行,取消命令
sed -n '/hello/!p' data.txt 除了包含hello的行不打印,其他的都打印出来
sed -n '{1!G ; h ; $p }' data.txt 反转输出文本内容,类似tac命令
分支命令:
[address]b [label] b放在寻址的后面
例:
cat data.txt
this xxx xxx xxx xxx
this xxx xxx xxx xxx
xxxx xxx bbb xxx xxx
sed命令写法:
sed '{
/bbb/b jump ; #匹配到bbb就跳转到jump位置,并执行jump后面的命令
s/this/xxx/ ; #其他行执行的命令
:jump ; #冒号后面放label标签
s/bbb/XXX/ ;
}' data.txt
处理结果:
xxx xxx xxx xxx xxx
xxx xxx xxx xxx xxx
xxxx xxx XXX xxx xxx
测试:
例:
sed '{
s/hello/xxx/ #如果成功替换了这条,就不执行下一条替换,否者执行下一条替换
t
s/world/xxx/
}' data.txt
无限循环示例:
sed -n '{
:start
s/hello/xxx/1p #如果替换成功就会跳转到start再次执行替换,1表示匹配到的第一个
t start
}' data.txt
跳转符号最长为7个字符。
模式替代:
&符号
同正则中的 \1 \2
echo "This is a cat" | sed 's/.at/"&"/g'
子模式:
\1 \2 如同正则中的子模式
例1:echo "This is a cat" | sed 's/\(.at\)/"\1"/g'
例2:在数字中插入逗号
echo "123456" | sed '{
:start
s/\(.*[0-9]\)\([0-9]\)\{3\}/\1,\2/
t start
}'
处理结果:1,234,567
在脚本中使用sed:
包装sed脚本:
在脚本reverse.sh中写入:
sed -n '{ 1!G ; h ; $p }' $1
这个$1参数用来接收要处理的文件名称,这样就不用每次都输入sed命令了,这个脚本功能同tac
重定向sed输出:
一个计算阶乘的示例:
#!/bin/bash
factorial=1
counter=1
number=$1
while [ $counter -le $number ]
do
factorial=$[ $factorial * $number ]
counter=$[ $counter + 1 ]
done
result=$(echo $factorial | sed '{
:start
s/\(.*[0-9]\)\([0-9]\{3\}\)/\1,\2/
t start
}')
echo "The result is $result"
创建sed实用工具:
sed 'G' data.txt 在文本的每行后面插入一个空行
sed '$!G' data.txt 最后一行不使用G命令,也就是说除了最后一行在每行后面都加入一个空行,$最后一行 !跳过
这个方法的技巧在于启动sed编辑器之后保持空间中只有一个空行。
对有空行的文本加空行:
问题的关键在于有两个空行的行就不用加倍空行了,所以要先删除空行,再加文本空行。
sed '/^$/d ; $!G' data.txt 先将所有的空行都删除了,然后将除了最后一行之外的其他行都加空行。
给文件中的行编号:
sed '=' test.txt | sed 'N ; s/\n/ /' 等于号=可以输出序号,但是有换行,再使用另一个sed命令处理掉换行,用N命令合并两行,再将换行替换掉
打印末尾行:
sed '{
>:start
>$q #$ 最后一行,q退出,表示遇到最后一行就退出sed,q命令是退出命令
>N #N将下一行追加到模式空间
>11,$D #11,$D是当模式空间中有11行后,D命令就会删除空间中第一行
>b start #循环上面的过程
>}' test.txt
这样就会得到最后的10行文本内容
删除行
删除连续的空白行:
sed '/./,/^$/!d' data.txt /./表示开始区间必须不是空白行,/^$/结束区间是空白行,!d表示不删除,连起来就是区间内的空白行不会被删除,如果文本有两个以上的空白行只会一个空白行。
删除开头的空白行:
sed '/./,$!d' data.txt /./表示非空行的开始区间,$表示最后一行,!d表示不删除;意思就是从有内容的行开始到最后一行都不删除,这样只有开头的空白行才会被删除了。
删除注释和空行:
sed '/^#\|^$/d' demo.conf
删除结尾的空行:
sed '{
:start
/^\n*$/{$d ; N ; b start} /^\n*$/这个能匹配只含有一个换行符的行
}'
$d表示是最后一行就删除,N将下一行附加到模式空间,这样每一次循环就删除最后一行空行。
注意:括号中包括括号,这是命令分组,可以将该组命令只作用在地址区间中。
显示奇数行:
sed -n '1~2p' data.txt 使用1~2表示步进地址,1表示从第一行,2表示步进为2,显示偶数可以使用2~2表示。
删除HTML标签:
sed 's/<[^>]*>//g' data.txt
sed 's/<[^>]*>//g ; /^$/d' data.txt 顺带删除空行