sed命令

sed命令

sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内容并没有 改变,除非你使用重定向存储输出。Sed主要用来自动编辑一个或多个文件;简化对文件的反复操作;编写转换程序等。

参数说明:

参数说明
-e以选项中指定的script来处理输入的文本文件
-f以选项中指定的script文件来处理输入的文本文件
-h或–help显示帮助
-n仅显示script处理后的结果
-V或–version 显示版本信息

动作说明:

动作说明
a新增,a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)
p打印,通常 p 会与参数 sed -n 一起运行
c取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行
d删除,删除选择的行;
D删除模板块的第一行
i插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
s取代,通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!
h拷贝模板块的内容到内存中的缓冲区;
H追加模板块的内容到内存中的缓冲区;
g获得内存缓冲区的内容,并替代当前模板块中的文本;
G获得内存缓冲区的内容,并追加到当前模板块文本的后面;
l列表不能打印字符的清单;
n读取下一个输入行,用下一个命令处理新的行而不是用第一个命令;
N追加下一个输入行到模板块后面并在二者间嵌入一个新行,改变当前行号码;
p打印模板块的行。 P(大写) 打印模板块的第一行;
q退出Sed;
rfile 从file中读行;
blable 分支到脚本中带有标记的地方,如果分支不存在则分支到脚本的末尾;
tlabel if分支,从最后一行开始,条件一旦满足或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾;
Tlabel 错误分支,从最后一行开始,一旦发生错误或者T,t命令,将导致分支到带有标号的命令处,或者到脚本的末尾;
wfile 写并追加模板块到file末尾;
Wfile 写并追加模板块的第一行到file末尾;
!表示后面的命令对所有没有被选定的行发生作用;
=打印当前行号;
#把注释扩展到下一个换行符以前;

sed替换标记:

g表示行内全面替换;
p表示打印行;
w表示把行写入一个文件;
x表示互换模板块中的文本和缓冲区中的文本;
y表示把一个字符翻译为另外的字符(但是不用于正则表达式);
\1子串匹配标记;
&已匹配字符串标记;

sed元字符集:

^匹配行开始,如:/^sed/匹配所有以sed开头的行;
$匹配行结束,如:/sed$/匹配所有以sed结尾的行;
.匹配一个非换行符的任意字符,如:/s.d/匹配s后接一个任意字符,最后是d;
*匹配0个或多个字符,如:/*sed/匹配所有模板是一个或多个空格后紧跟sed的行;
[]匹配一个指定范围内的字符,如/[ss]ed/匹配sed和Sed;
[^]匹配一个不在指定范围内的字符,如:/[^A-RT-Z]ed/匹配不包含A-R和T-Z的一个字母开头,紧跟ed的行;
\(…\)匹配子串,保存匹配的字符,如s/(love)able/\1rs,loveable被替换成lovers;
&保存搜索字符用来替换其他字符,如s/love/&/,love这成love;
<匹配单词的开始,如:/\
>匹配单词的结束,如/love>/匹配包含以love结尾的单词的行;
x{m}重复字符x,m次,如:/0{5}/匹配包含5个0的行;

练习:

①#全局替换:g
sed 's/book/books/g' file #/g 标记会替换每一行中的所有匹配
echo sksksksksksk | sed 's/sk/SK/2g' #需要从第N处匹配开始替换时,可以使用 /Ng
[root@zt ~]# echo sksksksksksk | sed 's/sk/SK/2g'            
skSKSKSKSKSK

②#定界符
命令中字符 / 在sed中作为定界符使用,也可以使用任意的定界符
sed 's:test:TEXT:g'     ---> :   :   :
sed 's|test|TEXT|g'   ---> |   |   |
#定界符出现在样式内部时,需要进行转义:
#组合多个表达式
sed 's/\/bin/\/usr\/local\/bin/g'
sed '表达式' | sed '表达式'
sed '表达式; 表达式'

③#删除:d
sed '/^$/d' file #删除空白行
sed '2d' file #删除第二行
sed '2,$d' file #删除第二行到最后一行
sed '$d' file  #删除最后一行
sed '/^test/'d file #删除以test开头的行

④#已匹配字符串标记&
#正则表达式 \w\+ 匹配每一个单词,使用 [&] 替换它,& 对应于之前所匹配到的单词
[root@zt ~]# echo "this is a test line" | sed 's/\w\+/[&]/g'
[this] [is] [a] [test] [line]

#所有以192.168.0.1开头的行都会被替换成它自已加localhost:
[root@zt ~]# sed 's/^192.168.0.1/&localhost/' file
hello
this is a test line
192.168.0.1localhost

⑤#子串匹配标记\1
#love被标记为1,所有loveable会被替换成lovers,并打印出来
sed -n 's/\(love\)able/\1rs/p' file

[root@zt ~]# echo this is digit 7 in a number | sed 's/digit\([0-9]\)/\1/'
this is digit 7 in a number
[root@zt ~]# echo this is digit 7 in a number | sed 's/digit \([0-9]\)/\1/'
this is 7 in a number
#命令中 digit 7,被替换成了 7。样式匹配到的子串是 7,\(..\) 用于匹配子串,
对于匹配到的第一个子串就标记为 \1,依此类推匹配到的第二个结果就是 \2

[root@zt ~]# echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\2 \1/'
BBB aaa
[root@zt ~]# echo aaa BBB | sed 's/\([a-z]\+\) \([A-Z]\+\)/\1/'
aaa
[root@zt ~]# echo abcd | sed 's/\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)/\2/'  
b
[root@zt ~]# echo abcd | sed 's/\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)\([a-z]\+\)/\1\2/'
ab

⑥#多点编辑,e
#-e选项允许在同一行里执行多条命令
sed -e '1,5d' -e 's/test/check/' file
#上面sed表达式的第一条命令删除1至5行,第二条命令用check替换test。
命令的执行顺序对结果有影响。如果两个命令都是替换命令,
那么第一个替换命令将影响第二个替换命令的结果

⑦#选定行的范围:,(逗号)
#所有在模板test和check所确定的范围内的行都被打印
sed -n '/test/,/check/p' file
#打印从第5行开始到第一个包含以mail开始的行之间的所有行:
[root@zt ~]# sed -n '5,/^mail/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
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
#对于模板test和west之间的行,每行的末尾用字符串aaa bbb替换
sed '/test/,/west/s/$/aaa bbb/' file

⑧#转换:y
#把1~10行内所有abcde转变为大写,注意,正则表达式元字符不能使用这个命令
sed '1,10y/abcde/ABCDE/' file

⑨#从文件读入:r
#file里的内容被读进来,显示在与test匹配的行后面,如果匹配多行,
则file的内容将显示在所有匹配行的下面
sed '/test/r file' filename

⑩#写入文件:w
#在example中所有包含test的行都被写入file里
sed -n '/test/w file' example

⑾#追加(行下):a
#将 this is a test line 追加到 以test 开头的行后面
sed '/^test/a\this is a test line' file
sed -i '2a\this is a test line' test.conf #第2行之后插入

⑿#插入(行上)
#i\命令 将 this is a test line 追加到以test开头的行前面
sed '/^test/i\this is a test line' file
sed -i '5i\this is a test line' test.conf

⒀#下一个:n
#如果test被匹配,则移动到匹配行的下一行,替换这一行的aa,变为bb,并打印该行,
然后继续
sed '/test/{ n; s/aa/bb/; }' file

测试:

1.以行为单位的删除

①将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除!
在这里插入图片描述
②只要删除第 2 行
在这里插入图片描述
③要删除第 3 到最后一行
在这里插入图片描述

2.以行为单位的新增

①在第三行后加上newline字样
在这里插入图片描述
在这里插入图片描述
②在第三行前加上newline字样
在这里插入图片描述
③在第二行后面加入两行字,例如newline1 和 newline2
在这里插入图片描述
注意:每一行之间都必须要以反斜杠『 \ 』来进行新行的添加

3.以行为单位的替换与显示

①将/etc/passwd中第2-5行的内容取代成为newline
在这里插入图片描述
②仅列出 /etc/passwd 文件内的第 5-7 行
在这里插入图片描述
③搜索 /etc/passwd有root关键字的行
在这里插入图片描述
如果root找到,除了输出所有行,还会输出匹配行。使用-n的时候将只打印包含模板的行。
在这里插入图片描述

4.数据的搜寻并删除

①删除/etc/passwd所有包含root的行,其他行输出
在这里插入图片描述
②删除/etc/passwd中第5-7行,其他行输出
在这里插入图片描述

5.数据的搜寻并执行命令

①搜索/etc/passwd,找到root对应的行,把bash替换为blueshell,再输出这行
在这里插入图片描述

6.数据的搜寻并替换命令

除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并代。
sed 's/要被取代的字串/新的字串/g’
在这里插入图片描述
在这里插入图片描述

7.多个命令同时编辑

①一条sed命令,删除/etc/passwd第3行到第五行的数据,并把sbin替换为bin
在这里插入图片描述
命令执行后:
在这里插入图片描述
注意:-e表示多点编辑,第一个编辑命令删除/etc/passwd第第3行到第五行的数据,第二条命令把sbin替换为bin。

8.直接修改文件内容(危险动作)

sed 可以直接修改文件的内容,不必使用管道命令或数据流重导向! 不过由于这个动作会直接修改到原始的文件,所以千万不要随便拿系统配置来测试!
在这里插入图片描述

练习:Week41.config

[root@zt ~]# cat Week41.config        
Steve Blenheim:238-923-7366:95 Latham Lane, Easton, PA 83755:11/12/56:20300

Betty Boop:245-836-8357:635 Cutesy Lane, Hollywood, CA 91464:6/23/23:14500

Igor Chevsky:385-375-8395:3567 Populus Place, Caldwell, NJ 23875:6/18/68:23400

Norma Corder:397-857-2735:74 Pine Street, Dearborn, MI 23874:3/28/45:245700

Jennifer Cowan:548-834-2348:583 Laurel Ave., Kingsville, TX 83745:10/1/35:58900

Jon DeLoach:408-253-3122:123 Park St., San Jose, CA 04086:7/25/53:85100

Karen Evich:284-758-2857:23 Edgecliff Place, Lincoln , NB 92743:7/25/53:85100

Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200

Karen Evich:284-758-2867:23 Edgecliff Place, Lincoln, NB 92743:11/3/35:58200

Fred Fardbarkle:674-843-1385:20 Parak Lane, Duluth, MN 23850:4/12/23:780900

Fred Fardbarkle:674-843-1385:20 Parak Lane, Duluth, MN 23850:4/12/23:780900

Lori Gortz:327-832-5728:3465 Mirlo Street, Peabody, MA 34756:10/2/65:35200

Paco Gutierrez:835-365-1284:454 Easy Street, Decatur, IL 75732:2/28/53:123500

Ephram Hardy:293-259-5395:235 CarltonLane, Joliet, IL 73858:8/12/20:56700

James Ikeda:834-938-8376:23445 Aster Ave., Allentown, NJ 83745:12/1/38:45000

Barbara Kertz:385-573-8326:832 Ponce Drive, Gzary, IN 83756:12/1/46:268500

Lesley Kirstin:408-456-1234:4 Harvard Square, Boston, MA 02133:4/22/62:52600

William Kopf:846-836-2837:6937 Ware Road, Milton, PA 93756:9/21/46:43500

Sir Lancelot:837-835-8257:474 Camelot Boulevard, Bath, WY 28356:5/13/69:24500

Jesse Neal:408-233-8971:45 Rose Terrace, San Francisco, CA 92303:2/3/36:25000

Zippy Pinhead:834-823-8319:2356 Bizarro Ave., Farmount, IL 84357:1/1/67:89500

Arthur Putie:923-835-8745:23 Wimp Lane, Kensington, DL 38758:8/31/69:126000

Popeye Sailor:156-454-3322:945 Bluto Street, Anywhere, USA 29358:3/19/35:22350

Jose Santiago:385-898-8357:38 Fife Way, Abilene, TX 39673:1/5/58:95600

Tommy Savage:408-724-0140:1222 Oxbow Court, Sunnyvale, CA 94087:5/19/66:34200

Yukio Takeshida:387-827-1095:13 Uno Lane, Ashville, NC 23556:7/1/29:57000

Vinh Tranh:438-910-7449:8235 Maple Street, Wilmington, VM 29085:9/23/63:68900
  1. 把Jon的名字改为Jonathan
    在这里插入图片描述
  2. 删除头3行
    在这里插入图片描述
  3. 打印第5~10行
    在这里插入图片描述
  4. 删除含有Lane的所有行
    在这里插入图片描述
  5. 打印所有生日在十一月或十二月的行
    在这里插入图片描述
  6. 在以Kare开头的行末尾加上3颗星
    在这里插入图片描述
  7. 将所有包含Jose的行都替换为JOSE HAS RETIRED
    在这里插入图片描述
  8. 把Popeye的生日改为11/14/46,假定您不知道Popeye的生日,设法用正则式查找出来
    在这里插入图片描述
  9. 删除所有空行
    在这里插入图片描述

sed扩展延伸版:难度++

/etc/passwd中的练习,为更简洁的表示 只取后三行

sshd❌74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ZT❌1000:1000::/home/ZT:/bin/bash
ALICE❌1001:1001::/home/ALICE:/bin/bash

  1. 删除文件每行的第一个字符
[root@zt ~]# sed 's/\(.\)\(.*\)/\2/' /etc/passwd | tail -3
shd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
T:x:1000:1000::/home/ZT:/bin/bash
LICE:x:1001:1001::/home/ALICE:/bin/bash
  1. 删除文件每行的第二个字符
 [root@zt ~]# sed 's/\(.\)\(.\)\(.*\)/\1\3/' /etc/passwd |tail -3  
shd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
Z:x:1000:1000::/home/ZT:/bin/bash
AICE:x:1001:1001::/home/ALICE:/bin/bash
  1. 删除文件每行的最后一个字符
[root@zt ~]# sed 's/\(.*\)\(.\)/\1/' /etc/passwd | tail -3  
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologi
ZT:x:1000:1000::/home/ZT:/bin/bas
ALICE:x:1001:1001::/home/ALICE:/bin/bas
  1. 删除文件每行的倒数第二个字符
[root@zt ~]# sed 's/\(.*\)\(.\)\(.\)/\1\3/' /etc/passwd | tail -3  
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologn
ZT:x:1000:1000::/home/ZT:/bin/bah
ALICE:x:1001:1001::/home/ALICE:/bin/bah
[root@zt ~]# 
  1. 删除文件每行的第二个单词
[root@zt ~]# sed 's/\([a-Z]\+\)\([^a-Z]\+\)\([a-Z]\+\)\(.*\)/\1\2\4/' /etc/passwd | tail -3 
sshd::74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ZT::1000:1000::/home/ZT:/bin/bash
ALICE::1001:1001::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 删除文件每行的倒数第二个单词
[root@zt ~]# sed -r 's/(.*)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]*$)/\1\2\4\5/' /etc/passwd| tail -3 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd://nologin
ZT:x:1000:1000::/home/ZT://bash
ALICE:x:1001:1001::/home/ALICE://bash
  1. 删除文件每行的最后一个单词
[root@zt ~]# sed -r 's/(.*)([^a-Z]+)([a-Z]+)([^a-Z]+)([a-Z]+)([^a-Z]*$)/\1\2\3\4/' //etc/passwd | tail -3 
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/
ZT:x:1000:1000::/home/ZT:/bin/
ALICE:x:1001:1001::/home/ALICE:/bin/
[root@zt ~]# 
  1. 交换每行的第一个字符和第二个字符
[root@zt ~]# sed -r 's/(.)(.)(.*)/\2\1\3/' /etc/passwd | tail -3  
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
TZ:x:1000:1000::/home/ZT:/bin/bash
LAICE:x:1001:1001::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 交换每行的第一个字符和第二个单词
[root@zt ~]# sed 's/\(^[a-Z0-9]\)\([a-Z0-9]*[^a-Z0-9]\{1,\}\)\([a-Z0-9]\{1,\}\)/\3\2\1/g'  /etc/passwd |tail -3  
xshd:s:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
xT:Z:1000:1000::/home/ZT:/bin/bash
xLICE:A:1001:1001::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 交换每行的第一个单词和最后一个单词
[root@zt ~]# sed -r 's/([a-Z]+)([^a-Z]+)(.*)([^a-Z]+)([a-Z]+)([^a-Z]*$)/\5\2\3\4\1\6/' /etc/passwd | tail -3  
nologin:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/sshd
bash:x:1000:1000::/home/ZT:/bin/ZT
bash:x:1001:1001::/home/ALICE:/bin/ALICE
[root@zt ~]# 
  1. 删除一个文件中所有的数字
[root@zt ~]# sed 's/[0-9]//g' /etc/passwd | tail -3  
sshd:x:::Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
ZT:x::::/home/ZT:/bin/bash
ALICE:x::::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 删除每行开头的所有空格
[root@localhost ~]# sed -r 's/^ +//g' /etc/grub2.cfg
......(省略)
### BEGIN /etc/grub.d/41_custom ###
if [ -f  ${config_directory}/custom.cfg ]; then
source ${config_directory}/custom.cfg
elif [ -z "${config_directory}" -a -f  $prefix/custom.cfg ]; then
source $prefix/custom.cfg;
fi
### END /etc/grub.d/41_custom ###
[root@localhost ~]#

  1. 用制表符替换文件中出现的所有空格
[root@zt ~]# sed -r 's/ +/\t/g' /etc/passwd  | tail -3
sshd:x:74:74:Privilege-separated        SSH:/var/empty/sshd:/sbin/nologin
ZT:x:1000:1000::/home/ZT:/bin/bash
ALICE:x:1001:1001::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 把所有大写字母用括号()括起来
[root@zt ~]# sed -r 's/([A-Z])/(\1)/g' /etc/passwd | tail -3
sshd:x:74:74:(P)rivilege-separated (S)(S)(H):/var/empty/sshd:/sbin/nologin
(Z)(T):x:1000:1000::/home/(Z)(T):/bin/bash
(A)(L)(I)(C)(E):x:1001:1001::/home/(A)(L)(I)(C)(E):/bin/bash
[root@zt ~]# 
  1. 打印每行3次
[root@zt ~]# sed  'p;p' /etc/passwd | tail -3
ALICE:x:1001:1001::/home/ALICE:/bin/bash
ALICE:x:1001:1001::/home/ALICE:/bin/bash
ALICE:x:1001:1001::/home/ALICE:/bin/bash
[root@zt ~]# 
  1. 隔行删除
[root@zt ~]# sed  '0~2 {=;d}' /etc/passwd  
root:x:0:0:root:/root:/bin/bash
2
daemon:x:2:2:daemon:/sbin:/sbin/nologin
4
......
ZT:x:1000:1000::/home/ZT:/bin/bash
20
[root@zt ~]# 
  1. 把文件从第1行到第2行复制到第4行后面
    sed '1h;2,2H;4G' sed.txt sed '1{h;d};2,2{H;d};4g' sed.txt
[root@localhost ~]# more sed.txt
hello
linux
hi
world
[root@localhost ~]# sed '1h;2,2H;4G' sed.txt
hello
linux
hi
world
hello
linux
[root@localhost ~]#
  1. 只显示每行的第一个单词
[root@zt ~]# sed 's/\([a-Z]\+\)\([^a-Z]\+\)\(.*\)/\1/' /etc/passwd | tail -3  
sshd
ZT
ALICE
[root@zt ~]# 
  1. 打印每行的第一个单词和第三个单词
[root@zt ~]# sed 's/\([a-Z]\+\)\([^a-Z]\+\)\([a-Z]\+\)\([^a-Z]\+\)\([a-Z]\+\)\([^a-Z]\+\)\(.*\)/\1\t\5/' /etc/passwd | tail -n 3  
sshd    Privilege
ZT      home
ALICE   home
[root@zt ~]# 
  1. 将格式为 mm/yy/dd 的日期格式换成 mm;yy;dd
[root@zt ~]# date '+%m/%y/%d' |sed 's#/#; #g'
10; 18; 31
[root@zt ~]# 

21.只显示IP地址

[root@zt ~]# ifconfig | egrep 'inet' | grep -v 'inet6'
        inet 192.168.163.135  netmask 255.255.255.0  broadcast 192.168.163.255
        inet 127.0.0.1  netmask 255.0.0.0
[root@zt ~]# ifconfig | egrep 'inet' | grep -v 'inet6' | sed 's/^.*inet//g'
 192.168.163.135  netmask 255.255.255.0  broadcast 192.168.163.255
 127.0.0.1  netmask 255.0.0.0
[root@zt ~]# ifconfig | egrep 'inet' | grep -v 'inet6' | sed 's/^.*inet//g' | sed 's/netmask.*$//g'
 192.168.163.135  
 127.0.0.1  

22.去掉ssh配置文件中的带#行和空行

more /etc/ssh/sshd_config
more /etc/ssh/sshd_config | sed 's/#.*$//g'
more /etc/ssh/sshd_config | sed 's/#.*$//g' | sed '/^$/d'
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值