0%

SED命令实践

  1. sed命令执行时包含了若干个循环(cycle),而每个循环又包含若干个命令(command),完整的执行流程图为(图片来源):

    The Sed execution model

  2. tips: 如果sed语法的第一个字符是“/”,那么表示这是一个正则表达式的地址定位方式。(细品)

  3. sed使用场景示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    echo 'line 1\nline 2\nline 3' | sed 's/line/"&"/g' #将所有的line加上双引号
    echo 'line\t1\nline\t2\nline\t3' | sed -n 'l' #显示文本中的控制字符
    echo 'line 1\nline 2\nline 3' | sed -n '/1/=' #显示包含1的行的行号,输出:1
    echo 'line 1\nline 1\nline 2\nline 3' | sed -n '$=' #显示总行数,输出:3

    #删除某几行文字(可以延伸到保留某几行,或删除或保留匹配的行)
    echo 'line 1\nline 2\nline 3' | sed '1d' #删除第1行
    echo 'line 1\nline 2\nline 3' | sed -n '1!p' #功能同上

    #sed默认会将pattern space中的数据输出到屏幕,如果使用FLAG p,还会每次额外把current pattern space输出到屏幕,举例
    echo 'line 1\nline 2\nline 3' | sed '/.*/p' #匹配所有的字符,并且会把pattern space和current pattern space中的内容都输出到屏幕上,因此每一行文字都会重复输出两次
    echo 'line 1\nline 2\nline 3' | sed -n '/1/p' #匹配包含“1”的行,但是-n选项会禁止pattern space输出到屏幕,而FLAG p又会把current pattern space中的内容都输出到屏幕上,因此屏幕上显示的是:line 1,也即实现了grep的功能。记住:option -n和command p是一家。

    #在日常工作中,经常需要使用sed进行替换(例如部署服务器时,进行模板变量的替换),而需求是屏幕上只输出被修改的行,可以使用FLAG w将修改内容输出的stdout,如下所示:
    ☺ cat 1.txt
    123
    456
    789
    zhengtongshan@DESKTOP-R7DT0R0 /mnt/e/Tetris/src/1_Branches/rtm_tetris_zhugan
    ☺ sed -i 's/1/s/gw /dev/stdout' 1.txt
    s23
    zhengtongshan@DESKTOP-R7DT0R0 /mnt/e/Tetris/src/1_Branches/rtm_tetris_zhugan
    ☺ cat 1.txt
    s23
    456
    789

    #在日常工作中,会遇到将制定的两行合并为一行的情况,情景为:如果发现某行包含某个字符,则将下面一行和本行合并,如下面的例子,如果行的第一个字符为a,则将后面的一行合并过来
    echo 'a\nb\nc\na\nb' |sed -e '/^a/N' -e 's/\n//'
    ab
    c
    ab

    #下面两个语句是等效的:(细品)
    man cp | sed 's/copy/{&}/w cp.txt' #将man page中的〝copy〞字串加上大括号〝{}〞,并将current pattern space写入“cp.txt”
    man cp | sed -n 's/copy/{&}/p' > cp.txt

    #多个FLAG可以叠加使用,但是和其他Linux指令一样,与文件有关的FLAG要放在最后
    man cp | sed 's/copy/{&}/Igpw cp.txt' #不区分大小写(FLAG I)将每行 (FLAG g)的“copy”加上大括号(Command s),将pattern space输出到屏幕(FLAG p),并将current pattern space写入文件“cp.txt”(FLAG w)
    echo 'line 1\n\nline 2\nline 3' | sed '/^$/d' #删除空白行
    echo 'line 1\nline 2\nline 3\nline 4' | sed -e 'N' -e 'N' -e 's/\n/+/g' #用两次N连续读取两个下一行(此时pattern space里有三行),然后把换行符都换成+,执行完毕后,输出为:
    line 1+line 2+line 3
    line 4
  4. 使用t label可以实现事务性的修改,比如两个替换要么同时进行,要么就都不做。

  5. command n命令的流程是:1、如果没有配置地址或匹配则输出pattern space(如果不满足则跳过下一步);2、然后读取下一行到pattern space。详情参考:Sed 命令完全指南中的次行命令一节,例如:

    1
    echo 'line 1\nline 2\nline 3\nline 4\nline 5\nline 6' | sed -e 'n' -e 'n' -ne 'p' #当第1个n执行后,pattern space变成:line 2,当第2个n执行后,pattern space变成:line 3,然后执行p后,打印current pattern space:line 3,然后进入下一个循环,打印出:line 6,上述sed可以简写成:sed -ne 'n;n;p',此外我们发现p命令的n选项是一个全局选项,它对整个sed语句生效而不仅限于p命令自己
  6. command N、D可以实现联合多行条件判断(例如:满足某一行有ID字符串,且下面两行分别包含NAME和ADDRESS字符串,则执行删除ID行的操作),实现更复杂的操作,如果不使用command N、D,那么sed的操作仅限于行内。

  7. command D为删除current pattern space的第一个字符到换行,而command P类似,只是将删除变为打印。

  8. command c和s的区别在于,前者是整行替换,后者还需要指定要替换的pattern。