sed 命令用于对文本进行过滤和变形处理,是一种流编辑器。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有改变,除非你使用重定向存储输出。
sed 命令主要用来自动编辑一个或多个文件,可以将数据行进行替换、删除、新增、选取等特定工作,简化对文件的反复操作,编写转换程序等。
命令格式 sed 命令格式如下:
1 2 3 4 5 sed [选项] '动作' file 或者将sed的command 写在一个文件内 sed [选项] -f scriptfile file
选项 sed命令中的选项是可选的,包含以下选项:
-e:直接在命令行模式上进行sed动作编辑,这个选项为默认选项;
-f:将sed的动作写在一个文件内,用-f scriptfile 的方式来执行该文件内的动作;
-i:直接修改文件内容;
-n:只打印模式匹配的行,其他内容不打印;
-r:支持扩展表达式;
-h或--help:显示帮助信息;
-V或--version:显示版本信息。
动作 动作的语法分为查询和修改两个部分,两部分的语法都不一样。
修改 sed命令的关于修改的语法如下:
1 sed [匹配条件][基础动作]\[要添加或者取代的字符串]
匹配条件:这里的匹配条件可以是指定行数,也可以像正则表达式一样去动态匹配,不过匹配规则是后面要提到的元字符集;
基础动作:这里就对上一个步骤中匹配到的行进行的动作,包括新增行、删除行、替换行、替换指定字符、打印等等;
要添加或者取代的字符串:当基础动作为新增、替换行、替换指定字符时,当字段就必须要填,否则可以不填。
说明 语法在一些特殊动作是会与上述语法有差别,比如当基础动作为s时,语法格式就会变为:
还有一个选项就是全面替换g标记
1 [匹配条件]/s/[匹配的字符]/[新的字符]/g
代表会替换每一行中的所有匹配。
动作包含以下基础动作:
a:在当前行下面插入文本;
i:在当前行上面插入文本;
c:把选定的行替换为新的文本;
d:删除当前行;
p:打印当前行;
s:替换指定字符
查询 sed命令关于查询时语法如下:
查询条件基本是一些字符串,而基础动作在查询是一般是p,也有可能是执行的一组命令;
如果是执行命令时,那使用花括号括起来,命令之间使用分号分割:
1 sed -n '/oo/{s/oo/kk/;p}' param.txt
以上命令则是找到 oo 对应的行,执行后面花括号中的一组命令,将oo 替换为kk,然后输出。
元字符集 该字符集是用于在sed中的匹配条件的编写,支持一些动态规则的匹配,语法如下:
^:匹配行开始,/^sed/就匹配所有以sed开头的行;
$:匹配行结束,/sed$/就匹配所有以sed结尾的行;
.:匹配一个非换行符的任意字符,/s.d/匹配s后接一个任意字符结尾是d的字符串;
*:匹配0个活多个字符,/*sed/匹配所有是一个或多个空格后紧跟sed的行;
[]:匹配一个指定范围内的字符,/[sS]/ed/匹配sed和Sed;
[^]:匹配一个不在指定范围内的字符,/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行;
x\{m\}:重复字符x,m次,/0\{5\}/就匹配包含5个0的行;
x\{m,\}:重复字符x,至少m次,/0\{5,\}就匹配至少有5个0的行;
x\{m,n\}:重复字符x,至少m次,不多于n次,/0\{5,9\}就匹配至少5个0,但不多于9个0的行。
示例 下面示例使用/etc/passwd文件作为输入,使用nl命令去将文件内的每一行添加行号,取前面10行保存成新文件。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 nl /etc/passwd | head -n 10 >> param.txtcat param.txt 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
在指定行添加字符串 添加行的话要确定是在指定行前面加还是后面加,确定这个之后就可以敲命令了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 sed '4a\newLine' param.txt ❯ sed '4a\newLine' param.txt 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin newLine 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
命令中的4就是匹配条件,a就是基础动作,\后面跟的就是要添加的newLine字符串。
上面例子就是使用a基础动作,在第4行后面添加newLine 字符串。如果想在第4行前面也就是第3行后面,上面的基础动作就从a替换到i。
那如何添加多行字符串呢?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 sed '2a\oneLine\ > twoLine' param.txt 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin oneLine twoLine 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
每一行之间都必须要以反斜杠 \ 来进行新行标记。
注意事项 注意,在 oneLine\ 后的下一行里,行首的> 不是我们敲的,是系统自动生成的。
以行为单位范围删除 将参数文件内的第2~5行删除
1 2 3 4 5 6 7 sed '2,5d' param.txt 1 root:x:0:0:root:/root:/bin/bash 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
上述命令的动作为2,5d,基础动作是d,将匹配条件2,5的行进行删除,在输出中也可以看出,2-5行已经被删除了。
除了删除指定范围行,也可以删除从指定行到最后一行,使用不知道最后一行的行数场景:
1 2 3 sed '3,$d' param.txt 1 root:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
上述命令就删除了从第三行开始,到最后一行的内容。
以行为单位的替换和显示 将第2-5行的内容取代成为 No 2-5 number
1 2 3 4 5 6 7 8 sed '2,5c\No 2-5 number' param.txt 1 root:x:0:0:root:/root:/bin/bash No 2-5 number 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
仅列出文件内的第5-7行
1 2 3 4 sed -n '5,7p' param.txt 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
使用-n选项,只打印那些匹配的行,使用5,7p动作,匹配条件是5,7,基础动作是p,意思是打印。
数据匹配 搜索param.txt文件中有root关键字的行
1 2 3 4 sed -n '/root/p' param.txt 1 root:x:0:0:root:/root:/bin/bash 11 root:x:0:0:root:/root:/bin/bash 12 root:x:0:0:root:/root:/bin/bash
数据匹配并删除 删除所有包含oo的行,其他行输出
1 2 3 4 5 6 7 8 sed '/oo/d' param.txt 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
数据匹配并执行命令 执行root对应的行,将root替换为superadmin,再输出。
1 2 3 4 5 6 7 8 9 10 11 12 13 sed '/root/{s/root/superadmin/}' param.txt 1 superadmin:x:0:0:root:/root:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin 11 superadmin:x:0:0:root:/root:/bin/bash 12 superadmin:x:0:0:root:/root:/bin/bash
从上面可以看出,所有行中的第一个root都被替换掉了,但如果我要每一行中的root都全部替换成superadmin,该如何做呢?
那就是在子命令中添加基础动作g,该动作是代表全局替换:
1 2 3 4 5 6 7 8 9 10 11 12 13 sed '/root/{s/root/superadmin/g}' param.txt 1 superadmin:x:0:0:superadmin:/superadmin:/bin/bash 2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin 3 bin:x:2:2:bin:/bin:/usr/sbin/nologin 4 sys:x:3:3:sys:/dev:/usr/sbin/nologin 5 sync :x:4:65534:sync :/bin:/bin/sync 6 games:x:5:60:games:/usr/games:/usr/sbin/nologin 7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin 8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin 9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin 10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin 11 superadmin:x:0:0:superadmin:/superadmin:/bin/bash 12 superadmin:x:0:0:superadmin:/superadmin:/bin/bash
从结果可以看出,所有的root都已经被替换成superadmin了。
参考资料