linux命令_sed

sed

sed命令

sed全称是:Stream EDitor(流编辑器。 Linux sed 命令是利用脚本来处理文本文件,sed 可依照脚本的指令来处理、编辑文本文件。Sed 主要用来自动编辑一个或多个文件、简化对文件的反复操作、编写转换程序等。

当处理数据时,sed 从输入源一次读入一行,并将它保存到所谓的模式空间pattern space中。所有 sed 的变换都发生在模式空间。变换都是由命令行上或外部 sed 脚本文件提供的单字母命令来描述的。大多数 sed 命令都可以由一个地址或一个地址范围作为前导来限制它们的作用范围。

选项 含义
-e 脚本命令 该选项会将其后跟的脚本命令添加到已有的命令中。
-f 脚本命令文件 该选项会将其后文件中的脚本命令添加到已有的命令中。
-n 默认情况下,sed 会在所有的脚本指定执行完毕后,会自动输出处理后的内容,而该选项会屏蔽启动输出,需使用 print 命令来完成输出。
-i 此选项会直接修改源文件,要慎用。

示例:

  • 查看passwd文件的第5到第8行内容

    [root@honey-master ~] sed -n '5,8 p' /etc/passwd
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    
  • 查看passwd文件中以roo开头的行

    [root@honey-master ~] sed -n '/^roo/ p' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    
  • 忽略大小写,对含有root字符的行打印出来

    [root@honey-master ~] sed -n '/root/I p' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    operator:x:11:0:operator:/root:/sbin/nologin
    
  • 直接查看passwd文件

    [root@honey-master ~] sed '' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    .......
    

    此时就不要配置-n参数了,因为-n是用来取消自动打印,配合查找规则一起用的

    但 p 标记会输出修改过的行,将二者匹配使用的效果就是只输出被替换命令修改过的行

  • 查找passwd文件中有/bin/bash字符串的行

    [root@honey-master ~] sed -n '\%/bin/bash% p' /etc/passwd
    root:x:0:0:root:/root:/bin/bash
    postgres:x:1000:1000::/home/postgres:/bin/bash
    
flags 标记 功能
n 1~512 之间的数字,表示指定要替换的字符串出现第几次时才进行替换,例如,一行中有 3 个 A,但用户只想替换第二个 A,这是就用到这个标记;
g 对数据中所有匹配到的内容进行替换,如果没有 g,则只会在第一次匹配成功时做替换操作。例如,一行数据中有 3 个 A,则只会替换第一个 A;
p 会打印与替换命令中指定的模式匹配的行。此标记通常与 -n 选项一起使用。
w file 将缓冲区中的内容写到指定的 file 文件中;
& 用正则表达式匹配的内容进行替换;
\n 匹配第 n 个子串,该子串之前在 pattern 中用 () 指定。
\ 转义(转义替换部分包含:&、\ 等)。
I 打印数据流中的文本和不可打印的ASCII字符(比如结束符s、制表符\t)
y 字符转换,转换之后的字符长度必须相同
c 将选定行内容替换成指定内容
d 删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
  • 将 /data/passwd 第2~5行删除打印输出

    image-20220519150618514

    image-20220519150947359

    可以看到这个删除打印,只是在输出时将源文件的2-5行过滤掉,并没有对文件进行任何的修改,如果我要对文件进行修改,就要用到sed -i的命令

删除
  • 删除文件第20行内容 sed -i '20 d' passwd

    image-20220519151308370

  • 删除文件之前备份命令

    sed -i.bak '20 d' passwd
    

    image-20220519151534106

新增
  • 在文件passwd上的第四行后面添加新字符串 ‘ivanlee’

    [root@honey-master data] sed -e 4a\ivanlee passwd
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    adm:x:3:4:adm:/var/adm:/sbin/nologin
    ivanlee
    lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
    sync:x:5:0:sync:/sbin:/bin/sync
    shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
    halt:x:7:0:halt:/sbin:/sbin/halt
    
  • 在文件中的第一行前面追加一个‘ivanlee’

    [root@honey-master data] sed '1 i\huawei' passwd
    huawei
    root:x:0:0:root:/root:/bin/bash
    bin:x:1:1:bin:/bin:/sbin/nologin
    daemon:x:2:2:daemon:/sbin:/sbin/nologin
    

    上面两个命令都对文件没有任何的修改,只是在打印时加了条件

  • 如果我想要在文件第一行就插入‘huawei’

    • 第一行起始位置插入

      [root@honey-master data] sed -i '1i huawei' passwd
      [root@honey-master data] cat -n passwd
           1  huawei
           2  root:x:0:0:root:/root:/bin/bash
           3  bin:x:1:1:bin:/bin:/sbin/nologin
           4  daemon:x:2:2:daemon:/sbin:/sbin/nologin
           5  adm:x:3:4:adm:/var/adm:/sbin/nologin
           6  lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
           7  sync:x:5:0:sync:/sbin:/bin/sync
           8  shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
      
    • 第二行末尾插入

      [root@honey-master data] sed -i '2a ivanlee' passwd
      [root@honey-master data] cat -n passwd
           1  huawei
           2  root:x:0:0:root:/root:/bin/bash
           3  ivanlee
           4  bin:x:1:1:bin:/bin:/sbin/nologin
      

    ai字符的相同点就是可以单独形成一行,但区别在于a是在一行之后,i在一行之前

  • sed -e:一次性可以执行多个命令

    [root@honey-master data] sed -e 's/huawei/vivo/g; s/ivanlee/Annnnn/g' passwd 
         1  vivo
         2  root:x:0:0:root:/root:/bin/bash
         3  Annnnn
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [root@honey-master data] cat passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/bash
         3  ivanlee
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    

sed脚本替换命令:

此命令的基本格式为:

[address]s/pattern/replacement/flags

其中,address 表示指定要操作的具体行,pattern 指的是需要替换的内容,replacement 指的是要替换的新内容。

关于指定具体操作行(address)的用法,这里先不做解释,文章后续会对其做详细介绍。

  • 指定 sed 用新文本替换第几处模式匹配的地方:

    [root@honey-master data] sed 's/:/---/3' passwd
    huawei
    root:x:0---0:root:/root:/bin/bash
    ivanlee
    bin:x:1---1:bin:/bin:/sbin/nologin
    daemon:x:2---2:daemon:/sbin:/sbin/nologin
    
    
    [root@honey-master data] sed 's/:/---/1' passwd
    huawei
    root---x:0:0:root:/root:/bin/bash
    ivanlee
    bin---x:1:1:bin:/bin:/sbin/nologin
    daemon---x:2:2:daemon:/sbin:/sbin/nologin
    

    可以看到后面的数字代表的就是在哪个位置发生改变,使用数字 1 作为标记的结果就是,sed 编辑器只替换每行中第 1 次出现的匹配模式。

  • 如果要用新文件替换所有匹配的字符串,可以使用 g 标记:

    [root@honey-master data] sed 's/:/---/g' passwd
    huawei
    root---x---0---0---root---/root---/bin/bash
    ivanlee
    bin---x---1---1---bin---/bin---/sbin/nologin
    daemon---x---2---2---daemon---/sbin---/sbin/nologin
    
  • 使用w将会把修改后的内容存到命名的文件里

    image-20220519154134580

  • 在使用 s 脚本命令时,替换类似文件路径的字符串会比较麻烦,需要将路径中的正斜线进行转义,**sed 's//bin/bash//bin/ivansh/g' passwd **

    [root@honey-master data] cat passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/bash
         3  ivanlee
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [root@honey-master data] sed 's/\/bin\/bash/\/bin\/ivansh/g' passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/ivansh
         3  ivanlee
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
  • c 命令表示将指定行中的所有内容,替换成该选项后面的字符串。

    [root@honey-master data] sed 's/\/bin\/bash/\/bin\/ivansh/g' passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/ivansh
         3  ivanlee
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    [root@honey-master data] sed '3c ivanlee_changed' passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/bash
    ivanlee_changed
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
  • y 转换命令是唯一可以处理单个字符的 sed 脚本命令

    转换命令会对 inchars 和 outchars 值进行一对一的映射,即 inchars 中的第一个字符会被转换为 outchars 中的第一个字符,第二个字符会被转换成 outchars 中的第二个字符...这个映射过程会一直持续到处理完指定字符。如果 inchars 和 outchars 的长度不同,则 sed 会产生一条错误消息。

    [root@honey-master data] sed 'y/12345/abcde/' passwd 
         a  huawei
         b  root:x:0:0:root:/root:/bin/bash
         c  ivanlee
         d  bin:x:a:a:bin:/bin:/sbin/nologin
         e  daemon:x:b:b:daemon:/sbin:/sbin/nologin
    [root@honey-master data] cat passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/bash
         3  ivanlee
         4  bin:x:1:1:bin:/bin:/sbin/nologin
         5  daemon:x:2:2:daemon:/sbin:/sbin/nologin
    
  • q 命令的作用是使 sed 命令在第一次匹配任务结束后,退出 sed 程序,不再进行对后续数据的处理。

    [root@honey-master data] sed '2q' passwd 
         1  huawei
         2  root:x:0:0:root:/root:/bin/bash
    

    只是输出了2行就是因为q命令。

sed 脚本命令的寻址方式

前面在介绍各个脚本命令时,我们一直忽略了对 address 部分的介绍。对各个脚本命令来说,address 用来表明该脚本命令作用到文本中的具体行。

默认情况下,sed 命令会作用于文本数据的所有行。如果只想将命令作用于特定行或某些行,则必须写明 address 部分,表示的方法有以下 2 种:

  1. 以数字形式指定行区间;
  2. 用文本模式指定具体行区间。

以上两种形式都可以使用如下这 2 种格式,分别是:

[address]脚本命令

或者

address {
  多个脚本命令
}

以上两种形式在前面例子中都有具体实例,因此这里不再做过多赘述。

以数字形式指定行区间

当使用数字方式的行寻址时,可以用行在文本流中的行位置来引用。sed 会将文本流中的第一行编号为 1,然后继续按顺序为接下来的行分配行号。

在脚本命令中,指定的地址可以是单个行号,或是用起始行号、逗号以及结尾行号指定的一定区间范围内的行。这里举一个 sed 命令作用到指定行号的例子:

[root@localhost ~]#sed '2s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy dog

可以看到,sed 只修改地址指定的第二行的文本。下面的例子中使用了行地址区间:

[root@localhost ~]# sed '2,3s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy dog


在此基础上,如果想将命令作用到文本中从某行开始的所有行,可以用特殊地址——美元符($):

[root@localhost ~]# sed '2,$s/dog/cat/' data1.txt
The quick brown fox jumps over the lazy dog
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat
The quick brown fox jumps over the lazy cat

用文本模式指定行区间

sed 允许指定文本模式来过滤出命令要作用的行,格式如下:

/pattern/command

注意,必须用正斜线将要指定的 pattern 封起来,sed 会将该命令作用到包含指定文本模式的行上。

举个例子,如果你想只修改用户 demo 的默认 shell,可以使用 sed 命令,执行命令如下:

[root@localhost ~] grep demo /etc/passwd
demo:x:502:502::/home/Samantha:/bin/bash
[root@localhost ~] sed '/demo/s/bash/csh/' /etc/passwd
root:x:0:0:root:/root:/bin/bash
...
demo:x:502:502::/home/demo:/bin/csh
...

虽然使用固定文本模式能帮你过滤出特定的值,就跟上面这个用户名的例子一样,但其作用难免有限,因此,sed 允许在文本模式使用正则表达式指明作用的具体行。正则表达式允许创建高级文本模式匹配表达式来匹配各种数据。这些表达式结合了一系列通配符、特殊字符以及固定文本字符来生成能够匹配几乎任何形式文本的简练模式。

posted @ 2022-05-19 16:05  ivanlee717  阅读(628)  评论(0编辑  收藏  举报