路漫漫其修远兮
吾将上下而求索

linux文本编辑:sed命令

简介

grep:egrep,fgrep:文本过滤器
sed:stream editor:流编辑器,行编辑器
awk:文本格式化工具,报告生成器

sed是非交互式的编辑器。它不会修改文件,除非使用shell重定向来保存结果。默认情况下,所有的输出行都被打印到屏幕上。

sed编辑器逐行处理文件(或输入),并将结果发送到屏幕。具体过程如下:首先sed把当前正在处理的行保存在一个临时缓存区中(也称为模式空间),然后处理临时缓冲区中的行,完成后把该行发送到屏幕上。sed每处理完一行就将其从临时缓冲区删除,然后将下一行读入,进行处理和显示。处理完输入文件的最后一行后,sed便结束运行。sed把每一行都存在临时缓冲区中,对这个副本进行编辑,所以不会修改原文件。简化反复操作,编写转换程序等

sed [OPTION]... ‘script' [input-file]...    与正则表达式一起用

常用选项:
-n:不输出模式空间中的内容到屏幕
-e script,--expresion=script:多点编辑
-f /PATH/TO/SED_SCRIPT_FILE  每行一个编辑命令
-r,--regexp_extended:支持使用扩展正则表达式
-i:直接编辑原文件

下面是script介绍

script:地址定界编辑命令
    不给地址:对全文进行处理
    单地址:
        #:指定的行
        /pattern/:被此处模式所能匹配到的每一行
    地址范围:
        #,#
        #,+#
        /pat1/,/pat2/
    ~:步进
        1~2:奇数行,从第一行开始,步进为两行
        2~2:偶数行,从第二行开始,步进为两行
    编辑命令:
        d:删除模式空间匹配的行
        p:显示模式空间中的内容
        a \text:在行后面追加文本;支持使用\n实现多行追加
        i \text:在行前面插入文本;支持使用\n实现多行插入
        c \text:替换行为单行或多行文本
        w /path/to/somefile: 保存模式匹配的行至指定文件
        r /path/from/somefile:读取指定文件的文本至模式空间中匹配到的行后
        =:为模式空间中的行打印行号
        !:模式空间中匹配行取反处理
        s///:查找替换,支持使用其他分隔符,s@@@,s###,s$$$也就是后面的符号可以使用其他的符号,只要相同就行
        g:行内全局替换
        p:显示替换成功的行
        w /PATH/TO/SOME/FILE:将替换成功的行保存至文件中
        &:插入内容

示例:

下面的文件是测试用的文件

[root@master ~]#cat fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysfs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,sysfs                   /sys                    sysfs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

显示第2行内容

[root@master ~]#sed -n '2p' fstab 
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0

显示2到4行

[root@master ~]#sed -n '2,4p' fstab 
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysfs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0

显示能匹配到dev的行,不管在哪一行

[root@master ~]#sed -n '/dev/p' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0

显示从第3行开始,到第一次能匹配到dev的行,即第3行到从第3行后面第一次匹配到dev的所有行

[root@master ~]#sed -n '3,/dev/p' fstab 
3,sysfs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0

显示空白行的行号

[root@master ~]#sed -n '/^$/=' fstab 
10

显示空白行并打印空白行行号

[root@master ~]#sed -n -e '/^$/p' -e '/^$/=' fstab 

10

在匹配到字符的行下面的一行添加新的内容

[root@master ~]#sed '/sysfs/a\how are you\n i am ok' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysfs                   /sys                    sysfs   defaults        0 0
how are you
 i am ok
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,sysfs                   /sys                    sysfs   defaults        0 0
how are you
 i am ok
9,proc                    /proc                   proc    defaults        0 0

在匹配到字符的行上面的一行添加新的内容

[root@master ~]#sed '/sysfs/i\how are you\n i am ok' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
how are you
 i am ok
3,sysfs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
how are you
 i am ok
 8,sysfs                   /sys                    sysfs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

将所有出现匹配到字符的整行数据替换为后面的字符串,即原来的整行删除

[root@master ~]#sed '/sysfs/c\how are you\n i am ok' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
how are you
 i am ok
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
how are you
 i am ok
9,proc                    /proc                   proc    defaults        0 0

删除空白行,即最后一行空白行删除

[root@master ~]#sed '/^$/d' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysfs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,sysfs                   /sys                    sysfs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

全局替换,但是当一行数据有两处都有匹配到的字符串,只替换第一处,后面的不替换,如果要全部替换,后面要加g选项,///三个斜杠,可以换成其他的@@@,###

[root@master ~]#sed 's/sys/aaa/' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,aaafs                   /sys                    sysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,aaafs                   /sys                    sysfs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

下面是全部替换,加g选项

[root@master ~]#sed 's/sys/aaa/g' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,aaafs                   /aaa                    aaafs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,aaafs                   /aaa                    aaafs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

将出现匹配到字符串后面添加字符串

[root@master ~]#sed 's/sys/&aaa/g' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysaaafs                   /sysaaa                    sysaaafs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,sysaaafs                   /sysaaa                    sysaaafs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

将出现匹配到字符串前面添加字符串,也就是说&表示前面匹配到的字符,然后想怎么操作怎么操作

[root@master ~]#sed 's/sys/aaa&/g' fstab 
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,aaasysfs                   /aaasys                    aaasysfs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
8,aaasysfs                   /aaasys                    aaasysfs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

非常重要的一个选项:-i,直接操作文件,永久有效

[root@master ~]#sed -i 's/sys/&aaa/g' fstab 
[root@master ~]#cat fstab
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysaaafs                   /sysaaa                    sysaaafs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
 8,sysaaafs                   /sysaaa                    sysaaafs   defaults        0 0
9,proc                    /proc                   proc    defaults        0 0

删除以空格开头的行,第8行前面有空格被删除

[root@master ~]#sed '/^[[:space:]].*/d' fstab
1,tmpfs                   /dev/shm                tmpfs   defaults        0 0
2,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
3,sysaaafs                   /sysaaa                    sysaaafs   defaults        0 0
4,proc                    /proc                   proc    defaults        0 0
5,
6,tmpfs                   /dev/shm                tmpfs   defaults        0 0
7,devpts                  /dev/pts                devpts  gid=5,mode=620  0 0
9,proc                    /proc                   proc    defaults        0 0

sed在指定行上删除和添加字符

删除行首的#字符,打开注释部分代码,sed行首删除一个字符
sed -i '/snd-soc-wmt-fm34/s/^#//' fs_patch/load_drivers.sh  
-i表示在原始文件上进行修改。
s/^#//表示将字符串开头的#字符替换为空(即去除行首的#字符)
       s/regexp/replacement/
              Attempt  to  match  regexp  against  the  pattern  space.  If successful, replace that portion matched with replacement.  
              The replacement may contain the special character & to refer to that portion of  the  pattern space  which  matched,  
              and  the  special escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.
其中s/regexp/replacement/命令支持address ranges,在该脚本中使用的是正则表达式匹配确定address ranges的方式:
/snd-soc-wmt-fm34/表示匹配含有snd-soc-wmt-fm34字符串的行
       /regexp/
              Match lines matching the regular expression regexp.


除了使用/regexp/的方式匹配特定行,sed还支持直接指定行号的方式进行操作,则上面的脚本也可以使用采用下面的方式完成:
sed -i '49s/^#//' fs_patch/load_drivers.sh  
       number Match only the specified line number.

注意,上面的数字前后都没有任何的附加字符。



sed行首添加一个字符
sed -i '/snd-soc-wmt-fm34/s/^/#&/' fs_patch/load_drivers.sh  
注意,这里和上面的删除操作唯一的不同就在于s/^/#&/部分。其中,^字符匹配行首,#字符是一般字符表示添加该字符,&字符是我们这里需要重点关心的。
在上面的关于s/regexp/replacement/命令描述时有以下字段:

The replacement may contain the special character & to refer to that portion of  the  pattern space  which  matched,  and  the  special 
escapes \1 through \9 to refer to the corresponding matching sub-expressions in the regexp.

这里提到了两种特殊字符:

&:refer to that portion of  the  pattern space  which  matched,即表示前面的正则表达式匹配出来的部分,而在这里指的就是行首位置。实际上,
在此处我们完全可以不要&字符,也是可以完成任务的。
\1...\9:refer to the corresponding matching sub-expressions in the regexp,主要用于多匹配时(如匹配行中的特定位置)分别表示前面的正则表达式
匹配出来的部分,这里的多匹配需要使用()来进行分割,如上面的代码可以分别使用下面两种方式进行实现:

sed -i '/snd-soc-wmt-fm34/s/^/\1#/' fs_patch/load_drivers.sh  
sed -i '/snd-soc-wmt-fm34/s/^.∗/#\2/' fs_patch/load_drivers.sh  
具体内容请参考正则表达式相关知识。

其它
本例中是根据工作需要在行首添加和删除字符,如果是在行尾进行操作,则需要使用&通配符;而如果需要在行中的其它位置进行操作,则可能就需要使用到多匹配的方式。

作业:

删除/etc/grub2.conf文件中所有以空白开头的行行首的空白字符
sed -r 's$^[[:space:]]+$$' /etc/grub2.cfg
删除/etc/fstab文件中所有以#开头,后面至少跟一个空白字符的行的行首的#和空白字
sed -r 's/^#[[:space:]]+//' /etc/fstab
在/root/install.log每一行行首增加#号
sed -r 's/^/#&/' /etc/fstab
在/etc/fstab文件中不以#开头的行的行首增加#号
sed -r 's/^[^#]/#&/' /etc/fstab | sed 's/^$/#&/'
处理/etc/fstab路径,使用sed命令取出其目录名和基名
echo /etc/sysconfig/ | sed -r  's#[^/]+/?$##' 目录名  从后面开始找,要以/结尾的,/有没有都可以,
一直到前面的/而且这个/不能是开始的那个/,中间的字符都要找到,并且替换为空
echo "/etc/fst/sd" | sed   -r 's@(.*/)([^/]+/?)$@\1@'  取目录名
echo "/etc/fst/sd" | sed   -r 's@(.*/)([^/]+/?)$@\2@'  取基名  ,因为是贪婪模式,第一次的.*/就一直能匹配到sd前面的/
利用sed 取出ifconfig命令中本机的IPv4地址
ifconfig | sed -n 2p | sed -r  's/.*addr:(.*)  Bca.*/\1/'
ifconfig | sed -n 2p | sed -e  's/.*addr://' -e 's/ B.*//'----------------------
ifconfig | sed -n 2p | sed -r  's/.*addr:(.*)  Bca.*/\1/'
统计centos安装光盘中Package目录下的所有rpm文件的  以.分隔倒数第二个字段的重复次数
ls *.rpm | sed -r 's#.*\.(.*)\.rpm$#\1#' | sort  |uniq -c
ls *.rpm | rev  | cut -d. -f2 | rev | sort | uniq -c----------------------
复制/etc/rc.d/init.d/functions文件至/tmp目录;替换/tmp/functions文件中的/etc/sysconfig/init为/var/log
sed 's@/etc/sysconfig/init@/var/log@g' functions
删除/tmp/functions文件中所有以#开头,且#后面至少有一个空白字符的行的行首的#号

未经允许不得转载:江哥架构师笔记 » linux文本编辑:sed命令

分享到:更多 ()

评论 抢沙发

评论前必须登录!