[toc]

sed命令简介

sed处理时,有2个缓冲区:【pattern space】和【hold space】

sed执行过程:

先读入一行,去掉尾部换行符,存入【pattern space】,执行编辑命令。

处理完毕,除非加了-n参数,把现在的【pattern space】打印出来,在后边打印曾去掉的换行符。

把【pattern space】置空。 接着读下一行,处理下一行。

sed的默认输出:【pattern space】里的内容输出到标准输出。

sed的常用选项:

  • 【pattern space】里的内容不输出到标准输出:-n

  • 默认只能执行一个脚本,执行多个脚本:-e script, --expression=script

    可以有多个-e script

  • 如果要执行的脚本特别多,可以指定一个脚本文件:-f /path/to/sed_scirpt

    脚本文件里,每行一个编辑命令。

  • 支持使用扩展的正则表达式,默认是基本正则表达式:-r

  • 直接编辑原文件:-i

  • 把【pattern space】空间中的内容覆盖到【hold space】空间:h

  • 把【pattern space】空间中的内容追加到【hold space】空间,然后删除【pattern space】空间中的内容:H

  • 把【hold space】空间中的内容覆盖到【pattern space】空间:g

  • 把【hold space】空间中的内容追加到【pattern space】空间,然后删除【hold space】空间中的内容:G

  • 互换【hold space】【pattern space】里的内容:x

  • 把匹配到的行的下一行放入【pattern space】,并把匹配到的行删除掉:n

  • 把匹配到的行的下一行放入【pattern space】,不删除匹配到的行:N

  • 删除【pattern space】空间中的行:d

  • 删除多行模式下【pattern space】里的所有行。(比如用N了,【pattern space】里就有多行):D

编辑命令:

如果有多个命令,则用分号分隔。

删掉【pattern space】里的内容:d

删除start.sh的第二行到第六行。

 1# nl start.sh | sed '2,6d' 
 21	#!/bin/sh
 37	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
 48	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
 59	 > /dev/null 2>&1 &)
 610	/dev/null 2>&1
 711	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
 812	java -Dio.netty.leakDetectionLevel=ADVANCED \
 913	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1014	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1115	com.hitotek.docker.DockerApplication 1000  &)
1216	/dev/null
在行前插入:-i \text 支持使用\n实现多行插入
 1# nl start.sh | sed '3i \new line\nother line'
 2
 31	#!/bin/sh
 42	set -xv
 53	basepath="$( cd "$(dirname "$0")"&& pwd )"
 6new line
 7other line
 84	echo $basepath
 95	$(nohup java )
106	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
117	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
128	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
139	 > /dev/null 2>&1 &)
1410	/dev/null 2>&1
1511	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
1612	java -Dio.netty.leakDetectionLevel=ADVANCED \
1713	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1814	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1915	com.hitotek.docker.DockerApplication 1000  &)
2016	/dev/null
在行后插入:-a \text 支持使用\n实现多行插入
 1# nl start.sh | sed '3a \new line\nother line'
 2
 31	#!/bin/sh
 42	set -xv
 5new line
 6other line
 73	basepath="$( cd "$(dirname "$0")"&& pwd )"
 84	echo $basepath
 95	$(nohup java )
106	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
117	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
128	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
139	 > /dev/null 2>&1 &)
1410	/dev/null 2>&1
1511	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
1612	java -Dio.netty.leakDetectionLevel=ADVANCED \
1713	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1814	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1915	com.hitotek.docker.DockerApplication 1000  &)
2016	/dev/null
21
22# nl start.sh | sed '/java/a \#java被修改的'
替换行:-c \text 把匹配到的行,替换成text
 1# nl start.sh | sed '/java/c \#java被修改的'
 2
 31	#!/bin/sh
 42	set -xv
 53	basepath="$( cd "$(dirname "$0")"&& pwd )"
 64	echo $basepath
 7#java被修改的
 8#java被修改的
 97	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
108	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
119	 > /dev/null 2>&1 &)
1210	/dev/null 2>&1
13#java被修改的
14#java被修改的
1513	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1614	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1715	com.hitotek.docker.DockerApplication 1000  &)
1816	/dev/null
19

####保存匹配到的行,到指定文件中:-w ./sedw.txt

把带Java的行,保持到/tmp/fsnew

1# nl start.sh | sed -n '/java/w ./sedw.txt' 
2
3[root@localhost testsed]# ls
4sedw.txt  start.sh  testSed.sh  test.txt
5[root@localhost testsed]# cat sedw.txt 
65	$(nohup java )
76	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
811	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
912	java -Dio.netty.leakDetectionLevel=ADVANCED \

在匹配到的行的上一行,加上行号:=

在以java的行的上一行加上行号

 1# nl start.sh | sed '/java/=' 
 2
 3[root@localhost testsed]#  nl start.sh | sed '/java/='
 4     1	#!/bin/sh
 5     2	set -xv
 6     3	basepath="$( cd "$(dirname "$0")"&& pwd )"
 7     4	echo $basepath
 85
 9     5	$(nohup java )
106
11     6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
12     7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
13     8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
14     9	 > /dev/null 2>&1 &)
15    10	/dev/null 2>&1
1611
17    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
1812
19    12	java -Dio.netty.leakDetectionLevel=ADVANCED \
20    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
21    14	/home/htga/docker/docker/trunk/target/docker/docker.jar \
22    15	com.hitotek.docker.DockerApplication 1000  &)
23    16	/dev/null

匹配到的行不执行后面的命令;没匹配到的行执行后面的命令:!。注意:!处理命令之前。

删除不以#开头的行:

1# nl start.sh | sed '/^#/!d' /etc/fstab
2#
3[root@localhost testsed]# nl start.sh | sed '/java/!d'
4     5	$(nohup java )
5     6	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
6    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
7    12	java -Dio.netty.leakDetectionLevel=ADVANCED \
8

查找替换:

  • s/要替换的/替换成的/替换标记。它的分隔符/可以自己指定,常用的有s@@@,s###

替换标记:

  • 全局替换:g
  • 将替换成功的结果保存到文件:w /path/to/save
  • 显示替换成功的行:p

练习

1,删除test文件中所有以空白字符开头的行的行首的所有空白字符

 1#  nl start.sh | sed 's@^[[:space:]]\+@@'
 2
 31	#!/bin/sh
 42	set -xv
 53	basepath="$( cd "$(dirname "$0")"&& pwd )"
 64	echo $basepath
 75	$(nohup java )
 86	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
 97	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
108	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
119	 > /dev/null 2>&1 &)
1210	/dev/null 2>&1
1311	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
1412	java -Dio.netty.leakDetectionLevel=ADVANCED \
1513	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1614	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1715	com.hitotek.docker.DockerApplication 1000  &)
1816	/dev/null

2,删除包含java的行 和 config 的行

 1#  nl start.sh | sed -e 's@java@@' -e '/config/d'
 2     1	#!/bin/sh
 3     2	set -xv
 4     3	basepath="$( cd "$(dirname "$0")"&& pwd )"
 5     4	echo $basepath
 6     5	$(nohup  )
 7     6	$(nohup  -Dio.netty.leakDetectionLevel=ADVANCED \
 8     8	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
 9     9	 > /dev/null 2>&1 &)
10    10	/dev/null 2>&1
11    12	 -Dio.netty.leakDetectionLevel=ADVANCED \
12    14	/home/htga/docker/docker/trunk/target/docker/docker.jar \
13    15	com.hitotek.docker.DockerApplication 1000  &)
14    16	/dev/null

sed的常用查询方式

1、不给地址:对全文进行处理

  • nl start.sh |sed 'p'
 11	#!/bin/sh
 21	#!/bin/sh
 32	set -xv
 42	set -xv
 53	basepath="$( cd "$(dirname "$0")"&& pwd )"
 63	basepath="$( cd "$(dirname "$0")"&& pwd )"
 74	echo $basepath
 84	echo $basepath
 95	$(nohup java )
105	$(nohup java )
116	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
126	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
137	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
147	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
158	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
168	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
179	 > /dev/null 2>&1 &)
189	 > /dev/null 2>&1 &)
1910	/dev/null 2>&1
2010	/dev/null 2>&1
2111	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
2211	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
2312	java -Dio.netty.leakDetectionLevel=ADVANCED \
2412	java -Dio.netty.leakDetectionLevel=ADVANCED \
2513	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
2613	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
2714	/home/htga/docker/docker/trunk/target/docker/docker.jar \
2814	/home/htga/docker/docker/trunk/target/docker/docker.jar \
2915	com.hitotek.docker.DockerApplication 1000  &)
3015	com.hitotek.docker.DockerApplication 1000  &)
3116	/dev/null
3216	/dev/null
33
  • nl start.sh |sed -n 'p'
 11	#!/bin/sh
 22	set -xv
 33	basepath="$( cd "$(dirname "$0")"&& pwd )"
 44	echo $basepath
 55	$(nohup java )
 66	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
 77	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
 88	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
 99	 > /dev/null 2>&1 &)
1010	/dev/null 2>&1
1111	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
1212	java -Dio.netty.leakDetectionLevel=ADVANCED \
1313	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1414	/home/htga/docker/docker/trunk/target/docker/docker.jar \
1515	com.hitotek.docker.DockerApplication 1000  &)
1616	/dev/null 

2、单地址

  • #:指定行
1nl start.sh |sed -n '1p'  
2输出匹配的第一行
31	#!/bin/sh
4
  • /pattern/:被此模式所匹配到的每一行
1 nl start.sh |sed -n '/java/p'
2输出匹配的java的行
35	$(nohup java )
46	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
511	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
612	java -Dio.netty.leakDetectionLevel=ADVANCED \
7

3,地址范围

  • $:最后一行
1nl start.sh |sed -n '$p'
216	/dev/null
  • #,#:起始和结束
1nl start.sh |sed -n '3','5p'     或者   nl start.sh |sed -n '3','5'p
23	basepath="$( cd "$(dirname "$0")"&& pwd )"
34	echo $basepath
45	$(nohup java )
  • #,+#:起始,和从起始加多少行
1nl start.sh |sed -n '3','+5p'     或者   nl start.sh |sed -n '3','+5'p
23	basepath="$( cd "$(dirname "$0")"&& pwd )"
34	echo $basepath
45	$(nohup java )
56	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
67	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
78	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
  • #,/pat1/:起始到,pat1匹配到的行
1nl start.sh |sed -n '3','/docker/p'     或者   nl start.sh |sed -n '3','/docker/'p
2
33	basepath="$( cd "$(dirname "$0")"&& pwd )"
44	echo $basepath
55	$(nohup java )
66	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
77	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
8
  • /pat1/,/pat2/:pat1匹配到的行,到pat2匹配到的行
1nl start.sh |sed -n '/nohup/','/ADVANCED/'p     或者   nl start.sh |sed -n '3','/ADVANCED/'p
25	$(nohup java )
36	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
411	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
512	java -Dio.netty.leakDetectionLevel=ADVANCED \

4,步进:a~b

a为初始值 b为 步数

  • 1~2:1,3,5,7,9.。。行(所有奇数行)
 1nl start.sh |sed -n '1~2'p  
 2
 31	#!/bin/sh
 43	basepath="$( cd "$(dirname "$0")"&& pwd )"
 55	$(nohup java )
 67	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
 79	 > /dev/null 2>&1 &)
 811	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
 913	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
1015	com.hitotek.docker.DockerApplication 1000  &)
11
  • 2~2:2,4,6,8,10.。。行(所有偶数行)
1nl start.sh |sed -n '2~2'p 
22	set -xv
34	echo $basepath
46	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED \
58	/home/htga/docker/docker/trunk/target/docker/docker.jar com.hitotek.docker.DockerApplication 1000  \
610	/dev/null 2>&1
712	java -Dio.netty.leakDetectionLevel=ADVANCED \
814	/home/htga/docker/docker/trunk/target/docker/docker.jar \
916	/dev/null

sed比较复杂的例子

+ 取出最后一行:

1# nl start.sh | sed '$!d'  或  nl start.sh | sed -n '$p'
2
3[root@localhost testsed]# nl start.sh | sed '$!d'
4    16	/dev/null
5[root@localhost testsed]#  nl start.sh | sed -n '$p'
6    16	/dev/null
  • 第一种解释:
  1. 1-15行不是最后一行 ($ 最后一行 ) 执行到 $ 条件不满足
  2. !条件不满足的时候 反而要执行
  3. 执行d (删除 pattern space 输出 pattern space时为空)
  4. 16行 执行到 $ 条件满足
  5. !条件满足的时候 不执行
  6. 不执行d
  7. 输出 pattern space 即 16行
  • 第二种的解释
  1. 1-15行不是最后一行 ($ 最后一行 ) 执行到 $ 条件不满足
  2. 条件不满足的时候 不执行p 即 pattern space 有1-15行数据
  3. 16行 执行到 $ 条件满足
  4. 条件满足的时候 执行p 输出 16行数据
  5. -n 参数 不输出 pattern space 即 16行

显示奇数行:

1# nl start.sh | sed -n 'p;n'   或者 nl start.sh | sed -n '1~2p'
2     1	#!/bin/sh
3     3	basepath="$( cd "$(dirname "$0")"&& pwd )"
4     5	$(nohup java )
5     7	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker & -Xms256m -Xmx512m -classpath \
6     9	 > /dev/null 2>&1 &)
7    11	$(nohup java -Dio.netty.leakDetectionLevel=ADVANCED -Dglobal.config.path=$basepath -Xms256m -Xmx512m -classpath $basepath/docker.jar com.hitotek.docker.DockerApplication 1000 > /dev/null 2>&1 &)
8    13	-Dglobal.config.path=/home/htga/docker/docker/trunk/target/docker -Xms256m -Xmx512m -classpath \
9    15	com.hitotek.docker.DockerApplication 1000  &)
  1. p: pattern space 这行 复制到 hold space

  2. n:把要操作的行 往下一行 ;

执行流程解释

读入第一行 pattern space

执行p 把第一行的数据 直接输出

执行n 把第二行的【pattern space】数据删除 读入第三行的数据到 pattern space

没有 -n 再次输出第一行

执行p 把第三行的数据 直接输出

执行n 把第四行的【pattern space】数据删除 读入第五行的数据到 pattern space

没有 -n 再次输出第三行

执行p 把第五行的数据 直接输出

执行n 把第六行的【pattern space】数据删除 读入第七行的数据到 pattern space

没有 -n 再次输出第五行

………………

执行p 把第十五行的数据 直接输出

执行n 把第十六行的【pattern space】数据删除

复杂查询特定连续几行:

 1cat start.sh |
 2	sed /^#/d |   
 3	sed -n '/nohup/{
 4    p;
 5    /.*&.*/b endPo;
 6    :a;
 7    n;
 8    p;
 9    /.*&.*/!b a;
10    :endPo;
11    }' |  
12	sed -n '/nohup.*/{
13	/\\/!b endPo;p;
14	:a;n;
15	p;
16	/\\/b a;
17	:endPo;
18	}'
  • -n 只会输出匹配的行
  • ^特定开头
  • d 删除
  • p输出
  • b 跳跃某个节点
  • :a 指定a 节点
  • n 读下一行,并删除当前【pattern space】里的内容后,再把下一行的内容放入【pattern space】

其他相关例子

1 1,显示偶数行:
2 nl start.sh | sed -n 'n;p'
3 2,倒置文本:
4 nl start.sh | sed '1!G;h;$!d' 
5 
6 nl start.sh | sed 'G'

graph LR
A["[]矩形"]-->|"-->箭头"|B("()圆角")
B---|"---连线"|C(("双(())圆形"))
C==>|==粗线|D{"{}菱形"}
C-->E>">]为非对称"]