sed

sed

简介

sed 是 unix 下常用的文本处理工具之一,

常用法

  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
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
   # 先读取资料、存入模式空间、对其进行编辑、再输出、再用下一行替换模式空间内容
   # 调试工具sedsed (参数 -d)   http://aurelio.net/sedsed/sedsed-1.0
        -n   # 输出由编辑指令控制(取消默认的输出,必须与编辑指令一起配合)
        -i   # 直接对文件操作
        -e   # 多重编辑
        -r   # 正则可不转移特殊字符
        b    # 跳过匹配的行
        p    # 打印
        d    # 删除
        s    # 替换
        g    # 配合s全部替换
        i    # 行前插入
        a    # 行后插入
        r    # 读
        y    # 转换
        q    # 退出
        &    # 代表查找的串内容
        *    # 任意多个 前驱字符(前导符)
        ?    # 0或1个 最小匹配 没加-r参数需转义 \?
        $    # 最后一行
        .*   # 匹配任意多个字符
        \(a\)   # 保存a作为标签1(\1)

模式空间{
            # 模式空间(两行两行处理) 模式匹配的范围,一般而言,模式空间是输入文本中某一行,但是可以通过使用N函数把多于一行读入模式空间
            # 暂存空间里默认存储一个空行
            n   # 读入下一行(覆盖上一行)
            h   # 把模式空间里的行拷贝到暂存空间
            H   # 把模式空间里的行追加到暂存空间
            g   # 用暂存空间的内容替换模式空间的行
            G   # 把暂存空间的内容追加到模式空间的行后
            x   # 将暂存空间的内容于模式空间里的当前行互换# 对其前面的要匹配的范围取反
            D   # 删除当前模式空间中直到并包含第一个换行符的所有字符(/.*/匹配模式空间中所有内容,匹配到就执行D,没匹配到就结束D)
            N   # 追加下一个输入行到模式空间后面并在第二者间嵌入一个换行符,改变当前行号码,模式匹配可以延伸跨域这个内嵌换行
            p   # 打印模式空间中的直到并包含第一个换行的所有字符
        }


        标签函数{
            : lable # 建立命令标记,配合b,t函数使用跳转
            b lable # 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾。
            t labe  # 判断分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令出,或者到脚本末尾。与b函数不同在于t在执行跳转前会先检查其前一个替换命令是否成功,如成功,则执行跳转。
            sed -e '{:p1;/A/s/A/AA/;/B/s/B/BB/;/[AB]\{10\}/b;b p1;}'     # 文件内容第一行A第二行B:建立标签p1;两个替换函数(A替换成AA,B替换成BB)当A或者B达到10个以后调用b,返回
            echo 'sd  f   f   [a    b      c    cddd    eee]' | sed ':n;s#\(\[[^ ]*\)  *#\1#;tn'  # 标签函数t使用方法,替换[]里的空格
            echo "198723124.03"|sed -r ':a;s/([0-9]+)([0-9]{3})/\1,\2/;ta'  # 每三个字符加一个逗号
        }


  引用外部变量{
            sed -n ''$a',10p'
            sed -n ""$a",10p"
        }

        sed 10q                                       # 显示文件中的前10行 (模拟"head")
        sed -n '$='                                   # 计算行数(模拟 "wc -l")
        sed -n '5,/^no/p'                             # 打印从第5行到以no开头行之间的所有行
        sed -i "/^$f/d" a                           # 删除匹配行
        sed -i '/aaa/,$d'                             # 删除匹配行到末尾
        sed -i "s/=/:/" c                             # 直接对文本替换
        sed -i "/^pearls/s/$/j/"                      # 找到pearls开头在行尾加j
        sed '/1/,/3/p' file                           # 打印1和3之间的行
        sed -n '1p' file                              # 取出指定行
        sed '5i\aaa' file                             # 在第5行之前插入行
        sed '5a\aaa' file                             # 在第5行之后抽入行
        echo a|sed -e '/a/i\b'                        # 在匹配行前插入一行
        echo a|sed -e '/a/a\b'                        # 在匹配行后插入一行
        echo a|sed 's/a/&\nb/g'                       # 在匹配行后插入一行
        seq 10| sed -e{1,3}'s/./a/'                   # 匹配1和3行替换
        sed -n '/regexp/!p'                           # 只显示不匹配正则表达式的行
        sed '/regexp/d'                               # 只显示不匹配正则表达式的行
        sed '$!N;s/\n//'                              # 将每两行连接成一行
        sed '/baz/s/foo/bar/g'                        # 只在行中出现字串"baz"的情况下将"foo"替换成"bar"
        sed '/baz/!s/foo/bar/g'                       # 将"foo"替换成"bar",并且只在行中未出现字串"baz"的情况下替换
        echo a|sed -e 's/a/#&/g'                      # 在a前面加#号
        sed 's/foo/bar/4'                             # 只替换每一行中的第四个字串
        sed 's/\(.*\)foo/\1bar/'                      # 替换每行最后一个字符串
        sed 's/\(.*\)foo\(.*foo\)/\1bar\2/'           # 替换倒数第二个字符串
        sed 's/[0-9][0-9]$/&5'                        # 在以[0-9][0-9]结尾的行后加5
        sed -n ' /^eth\|em[01][^:]/{n;p;}'            # 匹配多个关键字
        sed -n -r ' /eth|em[01][^:]/{n;p;}'           # 匹配多个关键字
        echo -e "1\n2"|xargs -i -t sed 's/^/1/' {}    # 同时处理多个文件
        sed '/west/,/east/s/$/*VACA*/'                # 修改west和east之间的所有行,在结尾处加*VACA*
        sed  's/[^1-9]*\([0-9]\+\).*/\1/'             # 取出第一组数字,并且忽略掉开头的0
        sed -n '/regexp/{g;1!p;};h'                   # 查找字符串并将匹配行的上一行显示出来,但并不显示匹配行

        sed -n ' /regexp/{n;p;}'                      # 查找字符串并将匹配行的下一行显示出来,但并不显示匹配行
        sed -n 's/\(mar\)got/\1ianne/p'               # 保存\(mar\)作为标签1
        sed -n 's/\([0-9]\+\).*\(t\)/\2\1/p'          # 保存多个标签
        sed -i -e '1,3d' -e 's/1/2/'                  # 多重编辑(先删除1-3行,在将1替换成2)
        sed -e 's/@.*//g' -e '/^$/d'                  # 删除掉@后面所有字符,和空行
        sed -n -e "{s/^ *[0-9]*//p}"                  # 打印并删除正则表达式的那部分内容
        echo abcd|sed 'y/bd/BE/'                      # 匹配字符替换
        sed '/^#/b;y/y/P/' 2                          # 非#号开头的行替换字符
        sed '/suan/r readfile'                        # 找到含suan的行,在后面加上读入的文件内容
        sed -n '/no/w writefile'                      # 找到含no的行,写入到指定文件中
        sed '/regex/G'                                # 在匹配式样行之后插入一空行
        sed '/regex/{x;p;x;G;}'                       # 在匹配式样行之前和之后各插入一空行
        sed 'n;d'                                     # 删除所有偶数行
        sed 'G;G'                                     # 在每一行后面增加两空行
        sed '/^$/d;G'                                 # 在输出的文本中每一行后面将有且只有一空行
        sed 'n;n;n;n;G;'                              # 在每5行后增加一空白行
        sed -n '5~5p'                                 # 只打印行号为5的倍数
        seq 1 30|sed  '5~5s/.*/a/'                    # 倍数行执行替换
        sed -n '3,${p;n;n;n;n;n;n;}'                  # 从第3行开始,每7行显示一次
        sed -n 'h;n;G;p'                              # 奇偶调换
        seq 1 10|sed '1!G;h;$!d'                      # 倒叙排列
        ls -l|sed -n '/^.rwx.*/p'                     # 查找属主权限为7的文件
        sed = filename | sed 'N;s/\n/\t/'             # 为文件中的每一行进行编号(简单的左对齐方式)
        sed 's/^[ \t]*//'                             # 将每一行前导的"空白字符"(空格,制表符)删除,使之左对齐
        sed 's/^[ \t]*//;s/[ \t]*$//'                 # 将每一行中的前导和拖尾的空白字符删除
        sed '/{abc,def\}\/\[111,222]/s/^/00000/'      # 匹配需要转行的字符: } / [

        echo abcd\\nabcde |sed 's/\\n/@/g' |tr '@' '\n'        # 将换行符转换为换行
        cat tmp|awk '{print $1}'|sort -n|sed -n '$p'           # 取一列最大值
        sed -n '{s/^[^\/]*//;s/\:.*//;p}' /etc/passwd          # 取用户家目录(匹配不为/的字符和匹配:到结尾的字符全部删除)
        sed = filename | sed 'N;s/^/      /; s/ *\(.\{6,\}\)\n/\1   /'   # 对文件中的所有行编号(行号在左,文字右端对齐)
        /sbin/ifconfig |sed 's/.*inet addr:\(.*\) Bca.*/\1/g' |sed -n '/eth/{n;p}'   # 取所有IP

        修改keepalive配置剔除后端服务器{
            sed -i '/real_server.*10.0.1.158.*8888/,+8 s/^/#/' keepalived.conf
            sed -i '/real_server.*10.0.1.158.*8888/,+8 s/^#//' keepalived.conf
        }
        模仿rev功能{
            echo 123 |sed '/\n/!G;s/\(.\)\(.*\n\)/&\2\1/;//D;s/.//;'
            /\n/!G;               # 没有\n换行符,要执行G,因为保留空间中为空,所以在模式空间追加一空行
            s/\(.\)\(.*\n\)/&\2\1/;     # 标签替换 &\n23\n1$ (关键在于& ,可以让后面//匹配到空行)
            //D;                  # D 命令会引起循环删除模式空间中的第一部分,如果删除后,模式空间中还有剩余行,则返回 D 之前的命令,重新执行,如果 D 后,模式空间中没有任何内容,则将退出。  //D 匹配空行执行D,如果上句s没有匹配到,//也无法匹配到空行, "//D;"命令结束
            s/.//;                # D结束后,删除开头的 \n
        }

$ sed -n 'm'p      filename.txt
$ sed -n 'm,n'p     filename.txt
$ sed -n 'm,$'p     filename.txt
$ sed -n '/pattern1/'p filename.txt
$ sed -n '/pattern1/,$'p filename.txt
$ sed -n '/pattern1/,/pattern2/'p filename.txt
$ sed -n 'm,/pattern/'p filename.txt

## 删除首行,尾行
$ sed -n '1!P;N;$q;D'

参考

updatedupdated2024-05-102024-05-10