加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Linux > 正文

Linux sed命令

发布时间:2020-12-13 22:31:12 所属栏目:Linux 来源:网络整理
导读:sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下一行,这样不断重复,直到文件末尾。文件内

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

sed命令和选项

?命令 ?功能
?a

?在当前行后添加一行或多行。多行时除最后一行外,每行末尾需用“”续行

?c ?用此符号后的新文本替换当前行中的文本。多行时除最后一行外,每行末尾需用""续行
?i ?在当前行之前插入文本。多行时除最后一行外,每行末尾需用""续行
?d ?删除行
?h ?把模式空间里的内容复制到暂存缓冲区
?H ?把模式空间里的内容追加到暂存缓冲区
?g ?把暂存缓冲区里的内容复制到模式空间,覆盖原有的内容
?G ?把暂存缓冲区的内容追加到模式空间里,追加在原有内容的后面
?l ?列出非打印字符
?p ?打印行
?n ?读入下一输入行,并从下一条命令而不是第一条命令开始对其的处理
?q ?结束或退出sed
?r ?从文件中读取输入行
?! ?对所选行以外的所有行应用命令
?s ?用一个字符串替换另一个
?g ?在行内进行全局替换
?w ?将所选的行写入文件
?x ?交换暂存缓冲区与模式空间的内容
?y ?将字符替换为另一字符(不能对正则表达式使用y命令)




























?选项 ?功能
?-e ?进行多项编辑,即对输入行应用多条sed命令时使用
?-n ?取消默认的输出
?-f ?指定sed脚本的文件名






?

?

?

?

sed不向grep一样,不管是否找到指定的模式,它的退出状态都是0。只有当命令存在语法错误时,sed的退出状态才不是0。

sed使用参数
ubuntu@ubuntu156:~$ sed [-nefr] [动作]
选项与参数:
-n :使用安静(silent)模式。在一般 sed 的用法中,所有来自 STDIN 的数据一般都会被列出到终端上。但如果加上 -n 参数后,则只有经过sed 特殊处理的那一行(或者动作)才会被列出来。
-e :直接在命令列模式上进行 sed 的动作编辑;
-f :直接将 sed 的动作写在一个文件内, -f filename 则可以运行 filename 内的 sed 动作;
-r :sed 的动作支持的是延伸型正规表示法的语法。(默认是基础正规表示法语法)
-i :直接修改读取的文件内容,而不是输出到终端。

动作说明: [n1[,n2]]function
n1,n2 :不见得会存在,一般代表『选择进行动作的行数』,举例来说,如果我的动作是需要在 10 到 20 行之间进行的,则『 10,20[动作行为] 』

function:
a :新增, a 的后面可以接字串,而这些字串会在新的一行出现(目前的下一行)~
c :取代, c 的后面可以接字串,这些字串可以取代 n1,n2 之间的行!
d :删除,因为是删除啊,所以 d 后面通常不接任何咚咚;
i :插入, i 的后面可以接字串,而这些字串会在新的一行出现(目前的上一行);
p :列印,亦即将某个选择的数据印出。通常 p 会与参数 sed -n 一起运行~
s :取代,可以直接进行取代的工作哩!通常这个 s 的动作可以搭配正规表示法!例如 1,20s/old/new/g 就是啦!
?
正则表达式元字符
?与grep一样,sed也支持特殊元字符,来进行模式查找、替换。不同的是,sed使用的正则表达式是括在斜杠线"/"之间的模式。
如果要把正则表达式分隔符"/"改为另一个字符,比如o,只要在这个字符前加一个反斜线,在字符后跟上正则表达式,再跟上这个字符即可。例如:sed -n 'o^Myop' datafile
?元字符 ?功能 ?示例
?^ ?行首定位符 ?/^my/? 匹配所有以my开头的行
?$ ?行尾定位符 ?/my$/? 匹配所有以my结尾的行
?. ?匹配除换行符以外的单个字符 ?/m..y/? 匹配包含字母m,后跟两个任意字符,再跟字母y的行
?* ?匹配零个或多个前导字符 ?/my*/? 匹配包含字母m,后跟零个或多个y字母的行
?[] ?匹配指定字符组内的任一字符 ?/[Mm]y/? 匹配包含My或my的行
?[^] ?匹配不在指定字符组内的任一字符 ?/[^Mm]y/? 匹配包含y,但y之前的那个字符不是M或m的行
?(..) ?保存已匹配的字符 ?1,20s/(you)self/1r/? 标记元字符之间的模式,并将其保存为标签1,之后可以使用1来引用它。最多可以定义9个标签,从左边开始编号,最左边的是第一个。此例中,对第1到第20行进行处理,you被保存为标签1,如果发现youself,则替换为your。
?& ?保存查找串以便在替换串中引用 ?s/my/**&**/??符号&代表查找串。my将被替换为**my**
?&; ?词首定位符 ?/&;my/? 匹配包含以my开头的单词的行
?&; ?词尾定位符 ?/my&;/? 匹配包含以my结尾的单词的行
?x{m} ?连续m个x ?/9{5}/ 匹配包含连续5个9的行
?x{m,} ?至少m个x ?/9{5,}/? 匹配包含至少连续5个9的行
?x{m,n} ?至少m个,但不超过n个x ?/9{5,7}/? 匹配包含连续5到7个9的行
?
?
?

?

?

?

?

?

?













范例

以行为单位的新增/删除

(1)将 /etc/passwd 的内容列出并且列印行号,同时,请将第 2~5 行删除!

ubuntu@ubuntu156:~$ nl /etc/passwd | sed '2,5d'
1 root:x:0:0:root:/root:/bin/bash
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
11 uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin
  .....(后面省略).....

sed 的动作为 '2,5d' ,那个 d 就是删除!因为 2-5 行给他删除了,所以显示的数据就没有 2-5 行罗~ 另外,注意一下,原本应该是要下达 sed -e 才对,没有 -e 也行啦!同时也要注意的是, sed 后面接的动作,请务必以 '' 两个单引号括住喔!

(2)只要删除第 2 行

nl /etc/passwd | sed '2d' 

(3)要删除第 3 到最后一行

 nl /etc/passwd | sed '3,$d' 

(4)在第二行后(亦即是加在第三行)加上『drink tea?』字样!

ubuntu@ubuntu156:~$ nl /etc/passwd | sed '2a drink tea?'
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
drink tea?
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
4 sys:x:3:3:sys:/dev:/usr/sbin/nologin
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
  .....(后面省略).....

?(5)那如果是要在第二行前

 nl /etc/passwd | sed '2i drink tea' 

(6)如果是要增加两行以上,在第二行后面加入两行字,例如『Drink tea or .....』与『drink beer?』

ubuntu@ubuntu156:~$ nl /etc/passwd | sed '2a Drink tea or ......
> drink beer ?'
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
Drink tea or ......
drink beer ?
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
4 sys:x:3:3:sys:/dev:/usr/sbin/nologin
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
  .....(后面省略).....

每一行之间都必须要以反斜杠『 』来进行新行的添加喔!所以,上面的例子中,我们可以发现在第一行的最后面就有 存在。

?

以行为单位替换或显示


(1)将第2-5行的内容取代成为『No 2-5 number』呢?

ubuntu@ubuntu156:~$ nl /etc/passwd | sed '2,5c No 2-5 number'
1 root:x:0:0:root:/root:/bin/bash
No 2-5 number
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin
10 news:x:9:9:news:/var/spool/news:/usr/sbin/nologin
  .....(后面省略).....

透过这个方法我们就能够将数据整行取代了!

?

(2)仅列出 /etc/passwd 文件内的第 5-7 行

ubuntu@ubuntu156:~$ nl /etc/passwd | sed -n '5,7p'
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin

可以透过这个 sed 的以行为单位的显示功能, 就能够将某一个文件内的某些行号选择出来显示。

?

数据的搜寻并显示

(1)搜索 /etc/passwd有root关键字的行

ubuntu@ubuntu156:~$ nl /etc/passwd | sed '/root/p'
1 root:x:0:0:root:/root:/bin/bash
1 root:x:0:0:root:/root:/bin/bash
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
4 sys:x:3:3:sys:/dev:/usr/sbin/nologin
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
  ....下面忽略?

如果root找到,除了输出所有行,还会输出匹配行。

?

(2)使用-n的时候将只打印包含模板的行。

ubuntu@ubuntu156:~$ nl /etc/passwd | sed -n '/root/p'
1 root:x:0:0:root:/root:/bin/bash

?

数据的搜寻并删除

(1)删除/etc/passwd所有包含root的行,其他行输出

ubuntu@ubuntu156:~$
ubuntu@ubuntu156:~$ nl /etc/passwd | sed '/root/d'
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin
3 bin:x:2:2:bin:/bin:/usr/sbin/nologin
4 sys:x:3:3:sys:/dev:/usr/sbin/nologin
5 sync:x:4:65534:sync:/bin:/bin/sync
6 games:x:5:60:games:/usr/games:/usr/sbin/nologin
7 man:x:6:12:man:/var/cache/man:/usr/sbin/nologin
8 lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin
9 mail:x:8:8:mail:/var/mail:/usr/sbin/nologin

....下面忽略
#第一行的匹配root已经删除了

?

数据的搜寻并执行命令

(1)找到匹配模式eastern的行后,

搜索/etc/passwd,找到root对应的行,执行后面花括号中的一组命令,每个命令之间用分号分隔,这里把bash替换为blueshell,再输出这行:

ubuntu@ubuntu156:~$ nl /etc/passwd | sed -n '/root/{s/bash/blueshell/;p}'
1 root:x:0:0:root:/root:/bin/blueshell

(2)如果只替换/etc/passwd的第一个bash关键字为blueshell,就退出

ubuntu@ubuntu156:~$ nl /etc/passwd | sed -n '/bash/{s/bash/blueshell/;p;q}'
1 root:x:0:0:root:/root:/bin/blueshell

最后的q是退出。

?

数据的搜寻并替换

除了整行的处理模式之外, sed 还可以用行为单位进行部分数据的搜寻并取代。基本上 sed 的搜寻与替代的与 vi 相当的类似!他有点像这样:

sed 's/要被取代的字串/新的字串/g'

先观察原始信息,利用 /sbin/ifconfig 查询 IP

ubuntu@ubuntu161:~$ /sbin/ifconfig eno1
eno1 Link encap:Ethernet HWaddr 6c:92:bf:6e:6b:4e
inet addr:192.168.4.161 Bcast:192.168.4.255 Mask:255.255.255.0
inet6 addr: fe80::6e92:bfff:fe6e:6b4e/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1

.....(以下省略).....

本机的ip是192.168.4.161。

将 IP 前面的部分予以删除

ubuntu@ubuntu161:~$ /sbin/ifconfig eno1 | grep 'inet addr' | sed 's/^.*addr://g'
192.168.4.161 Bcast:192.168.4.255 Mask:255.255.255.0
ubuntu@ubuntu161:~$

说明 : 在?/sbin/ifconfig eno1 查找?'inet addr' 字段,??sed 's/^.*addr://g'? 在addr:所在的行中 从行首到addr:全部删除? ?得到?192.168.4.161 Bcast:192.168.4.255 Mask:255.255.255.0

?

接下来则是删除后续的部分,亦即:?192.168.1.100 Bcast:192.168.1.255 Mask:255.255.255.0

将 IP 后面的部分予以删除

ubuntu@ubuntu161:~$ /sbin/ifconfig eno1 | grep 'inet addr' | sed 's/^.*addr://g' | sed 's/Bcast.*$//g'

192.168.4.161

ubuntu@ubuntu161:~$
说明:在?/sbin/ifconfig eno1 查找?'inet addr' 字段,??sed 's/^.*addr://g'? 在addr:所在的行中 从行首到addr:全部删除? ?得到?192.168.4.161 Bcast:192.168.4.255 Mask:255.255.255.0

sed 's/Bcast.*$//g'? 行中包含Bcast到行尾的所有都删除? 得到?192.168.4.161

?

?

多点编辑

一条sed命令,删除/etc/passwd第三行到末尾的数据,并把bash替换为blueshell

ubuntu@ubuntu156:~$ nl /etc/passwd | sed -e '3,$d' -e 's/bash/blueshell/'
1 root:x:0:0:root:/root:/bin/blueshell
2 daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin

-e表示多点编辑,第一个编辑命令删除/etc/passwd第三行到末尾的数据,第二条命令搜索bash替换为blueshell。

?

?

?

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

sed 可以直接修改文件的内容,不必使用管道命令或数据流重导向! 不过,由於这个动作会直接修改到原始的文件,所以请你千万不要随便拿系统配置来测试! 我们还是使用下载的 regular_express.txt 文件来测试看看吧!

利用 sed 将 regular_express.txt 内每一行结尾若为 . 则换成 !

ubuntu@ubuntu156:~$ sed -i 's/.$/!/g' regular_express.txt

?

利用 sed 直接在 regular_express.txt 最后一行加入『# This is a test』

ubuntu@ubuntu156:~$ sed -i '$a # This is a test' regular_express.txt

由於 $ 代表的是最后一行,而 a 的动作是新增,因此该文件最后新增『# This is a test』!

sed 的『 -i 』选项可以直接修改文件内容,这功能非常有帮助!举例来说,如果你有一个 100 万行的文件,你要在第 100 行加某些文字,此时使用 vim 可能会疯掉!因为文件太大了!那怎办?就利用 sed 啊!透过 sed 直接修改/取代的功能,你甚至不需要使用 vim 去修订!



















?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读