sed命令详解

作者: ElephantKing | 来源:发表于2019-12-26 10:46 被阅读0次

    sed命令基本概念

    sed命令每次只能处理一行数据,数据的来源可以是:键盘输入、重定向、字符串、文件。每次从元数据读取一行放入缓冲区,依次执行sed命令,直到所有命令完成,再处理下一行。循环往复,直到所有数据行处理完成。
    sed命令常见的执行方式有两种,如下:

    1. shell命令中直接使用
    sed [option] 'command' input_file
    
    1. 把sed命令放在文件里,使用时用-f选项指定。
    sed [option] -f sed_script_file input_file
    

    sed命令选项

    sed命令的选项数量不多,使用起来也不复杂,主要一下几个:

    • -n:不打印所有的行到标准输出,配合p命令使用,输出实际操作的行。
    • -e:用于指定后面的串也是sed命令,用于连接多条sed命令。
    • -f:把所有sed命令放在一个文件里,执行时用-f选项指定文件名。
    • -i:in place。在输入文件上直接进行操作,会影响到输入文件。慎重使用。
    • -r:在sed的命令部分使用扩展正则语法。

    sed文本定位方式

    由于sed命令是基于行操作的命令,那么sed是如何定位某一行呢?主要有如下几种方式。

    1. 定位某一行
    • 用数字定位行,这是最简单粗暴的方式。
    # 打印input.txt的第4行,配合-n选项,其他的行不会被打印
    sed -n '4p' input.txt
    
    • 内置符号$,用于定位最后一行
    sed -n '$p' input.txt
    
    1. 定位某些行
    • 包含某个字符串的行,可以使用正则表达式,默认只支持基础正则语法,使用-r选项支持扩展正则语法。具体参见似是而非的正则语法规则。
    # 包含abc的行,查找字符串的语法必须是/xxx/前后两个斜杠都需要
    sed -n '/abc/p' input.txt
    # hello开头的行
    sed -n '/^hello/p' input.txt
    # 包含至少5个连续字母a的行,下面两个命令等价,原因参见上面的链接
    sed -n '/a\{5,\}/p' input.txt
    sed -n -r '/a{5,}/p' input.txt
    
    • 等差行号定位法
    # 定位奇数行,从第1行开始,步长为2
    sed -n '1~2p' input.txt
    # 从第10行起,步长为3,即输出10 13 16...行
    sed -n '10~3p' input.txt
    
    1. 定位一个区间的行:区间的两个端点可以是上面定位一行的方式的任意组合,用逗号隔开左右端点。示例如下:
    # 1-10行
    sed -n '1,10p' input.txt
    # 5到最后一行
    sed -n '5,$p' input.txt
    # 1到下一个(从下一行起,没有则到最后一行)包含abc的行
    sed -n '1,/abc/p' input.txt
    # 第一个包含abc的行到从此行开始下一个找到def的行,
    # 如果abc找不到则没有任何输出,def找不到则找到最后一行
    sed -n '/abc/,/def/p' input.txt
    

    行区间的定位还有另外一种方式,我把他叫做紧随其后行

    # 找到abc及其后3行,这里3的意思是再来3行
    # 左端点可以是上面定位一行的任意方式
    sed -n '/abc/,+3p' input.txt
    
    1. 反向选择上面的行
      在上述所有的行定位的方式的基础上,在其后面紧随一个!,表示反向选择行,示例如下:
    # 除了第1行都输出
    sed -n '1!p' input.txt
    # 偶数行
    sed -n '1~2!p' input.txt
    # 不包含abc的行
    sed -n '/abc/!p' input.txt
    

    sed行操作示例

    在上面的行定位中,我们只用了行处理的p操作。还有其他很多操作,如下:

    p:打印本行
    =:打印行号
    a\:在定位行后插入文本,可以插入多行,需要用\分隔
    i\:在定位行前插入文本
    d:删除定位行
    c\:用新文本替换定位行
    r:从另一个文本中读
    w:把定位行写入到一个文件
    y:把定位行的字符进行替换
    {}:在定位行执行一组命令
    s:使用替换模式
    
    还有复杂的和缓冲区相关的后面单独讲
    

    以上为常用处理操作,看示例吧

    # 打印包含abc的行
    sed -n '/abc/p' input.txt
    # 打印最后一行
    sed -n '$p' input.txt
    # 打印奇数行行号
    sed -n '1~2=' input.txt
    # 包含abc的行号
    sed -n '/abc/=' input.txt
    # 在20行后插入hello
    sed '20a\hello' input.txt
    # 1 4 7..行后插入what the fuck
    sed '1~3a\what the fuck' input.txt
    # 删除带abc的行
    sed -n '/abc/d' input.txt
    # 删除第一处包含abc的行及其后2两行
    sed -n '/abc/,+2d' input.txt
    # 把包含error的行,替换为what
    sed '/error/\cwhat' input.txt
    # 在包含John的行后面,插入文件score.txt的内容,和\a很像
    sed '/John/r score.txt' input.txt
    # 把定位的行输出到指定的文件中
    sed '/some lines/w out.txt' input.txt
    # 在定位行执行字符替换操作:把abc->ABC
    sed '1~2y/abc/ABC/' input.txt
    # 使用{}包括一组命令,按顺序执行,相当于用-e连接,下面命令等价,注意分号
    sed '/1~2{y/abc/ABC/;y/ABC/WTF/;}' input.txt
    sed -e '1~2y/abc/ABC/' -e '1~2y/ABC/WTF' input.txt
    # s替换字符串
    # abc->she
    sed 's/abc/she/' input.txt
    # 用()包围的内容,改为用{}包围,这里是贪心匹配,sed不支持非贪心模式
    sed 's/(\(.*\))/{\1}/g' input.txt
    # 替换默认只替换本行的第一个匹配,要替换所有请加g选项
    sed 's/abc/DEF/g' input.txt
    # 利用{}配合n选项进行操作,名字后面一行是成绩,用于修改成绩
    sed '/john/{n;s/score=59/score=100/;}' input.txt
    

    若sed命令放在shell脚本里,并且要使用shell中的变量时,请用双引号代替单引号包裹命令。

    高级用法,不常用

    两种缓冲区:模式缓冲区(pattern buffer)、保持缓冲区(hold buffer)
    五个缓冲区操作命令:

    • g: 将hold space中的内容拷贝到pattern buffer中,原来pattern buffer里的内容清除
    • G: 将hold buffer中的内容append到pattern buffer\n后
    • h: 将pattern buffer中的内容拷贝到hold buffer中,原来的hold space里的内容被清除
    • H: 将pattern buffer中的内容append到hold buffer\n后
    • x: 交换pattern buffer和hold buffer的内容
      初始情况下模式缓冲区和保持缓冲区内容为空,然后逐行读取内容到模式缓冲区,一般情况下就在模式缓冲区上操作,不会用到保持缓冲区,也不会影响到源文件,毕竟是拷贝过来的。上面五个命令就是在倒腾模式缓冲区保持缓冲区的内容。需要注意的两点是:
    1. 模式缓冲区的内容会被每次读取的行替代
    2. 保持缓冲区的内容不会主动变化,除非你用上面的h H x命令。
    # input.txt内容如下3行
    # one
    # two
    # three
    sed -n 'H;g;p;' input.txt
    # output:
    # 空行
    # one
    # 空行
    # one
    # two
    # 空行
    # one
    # two
    # three
    

    执行H命令时,模式缓冲区已经读入了第一行内容,所以执行H命令后,把第一行内容附加到保持缓冲区后,并且自动换行,再执行命令g把保持缓冲区的内容(一个空行 one)赋值回模式空间,再执行命令p把模式缓冲区的内容打印出来(打印的总是模式缓冲区的内容)。当读取下一行内容时,模式缓冲区又被替换为读取内容(two),保持缓冲区内容不变(一个空行 one),如此往复构成了这个执行结果。
    翻来覆去,一顿操作,暂时看不到使用场景,可以先放着吧。

    相关文章

      网友评论

        本文标题:sed命令详解

        本文链接:https://www.haomeiwen.com/subject/sypfoctx.html