linux 之sed用法

sed:Stream Editor文本流编辑,sed是一个“非交互式的”面向字符流的编辑器。在使用sed处理时,它把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接看用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕显示,接着处理下一行,不断重复直到文件末。默认情况下不会改变文件内容,除非使用了写入的命令,将内容更新。它的特点如下:

  • 1.它可以同时处理多个文件多行的内容(使用-e或者{})
  • 2.可以不对原文件改动,把整个文件输入到屏幕(不使用-i)
  • 3.可以把只匹配到模式的内容输入到屏幕上(使用-n)
  • 4.对原文件改动,但是不会再屏幕上返回结果(使用-i)

sed命令的语法格式:

  • sed的命令格式: sed [option] '[匹配模式] sed的内部命令' filename
  • sed的脚本格式:sed [option] -f 'sed script' filename

options 是可选的选择或参数
匹配模式 是可选的用于在文件中每一行进行匹配到模式,模式可以是正则,也可以是文件的行号
内部的命令也是可选的,但是两个单引号是必须的

sed命令的选项(option):

  • -n :只打印模式匹配的行
  • -e :直接在命令行模式上进行sed动作编辑,此为默认选项。。。使用多个-e可以进行多项编辑
  • -f :后跟脚本,是将sed的动作写在一个文件内,用–f filename 执行filename内的sed动作
  • -i :直接修改源文件内容,使用-i后不会再在终端输出文件内容
  • -r :支持扩展表达式
  • --follow-symlinks:
  • -l N, --line-length=N
  • --posix: disable all GNU extensions.
  • -s: consider files as separate rather than as a single continuous long stream.
  • -u,: load minimal amounts of data from the input files and flush the output buffers more often
  • -z, --null-data separate lines by NUL characters

sed的动作(sed command):

命令 解释 常用举栗

p

打印匹配行,因为sed默认打印文件中所有的行,所以使用p后匹配行会被打印两次

p可以跟-n配合使用,用于只打印匹配行

sed -n '2p' learn_sed.txt 打印第二行

sed -n '/^first/!p' learn_sed.txt 打印非first开头的行,注意!的位置

=

显示文件行号

 

a

在定位行号后插入新文本信息

  • sed '/first/i nihao' learn_sed.txt或sed '/first/inihao' learn_sed.txt 在匹配到first的行前新增一行nihao,i选项后的空格会被忽略
  • sed '/first/i  nihao\n 22' learn_sed.txt 添加多行时,多行间使用\n来换行,\n后的空格是被识别的
  • sed '1i testdata' myfile 在文件的行首添加一行
  • sed '$a testdata' myfile 在文件的行尾追加一行  
  • 同理使用-a时,在匹配行后添加一行,a/i后的空格会被忽略
  • sed '2a\1111111111111\ #在命令行执行时,除最后一行外换行都用\,但也可以自己在一行中用\n来分行 > 222222222222\ > 333333333333' /etc/hosts

i

在定位行号前插入新文本信息

c\

用新文本替换定位文本

d

删除定位行

sed的删除操作是针对文件的行,如果想删除行中的某个字符,那就用替换

  • sed '/^#/d' myfile 删除以#开头的行
  • sed '/^#/!d' myfile 删除非#开头的行,即显示以#开头的行
  • sed '1d' myfile 删除第一行
  • sed '$d' myfile 删除最后一行
  • sed '2,4d' myfile 删除指定的2~4行
  • sed '/\<line\>/d' learn_sed.txt #\<\>是单词界定符,删除行中有line单词的行。。如果某一行为firstline,由于字符串中的line不是个单词,所以该行不会删除

s

使用替换模式替换相应模式

s后紧跟的符号为地址定界符,一般由3个组成,定界符可以是/$#@等特殊字符

  • sed '/second/s/^/my /' learn_sed.txt #在匹配行的行首添加my。(先匹配后替换)
  • sed '/first/s/$/ END/' learn_sed.txt #在匹配行的行尾添加 END。(先匹配后替换)
  • sed 's/second/my &/' learn_sed.txt #在匹配字符串的前边添加my ,其中&代表替换字符串即second
  • sed 's/second/& my/' learn_sed.txt #在匹配字符串的后边添加 my。
  • sed '/first/s/\(.*\)/\1 END/' learn_sed.txt #使用正则方式在first所在行的行尾添加 END,其中\(\)表示分组,.*表示任意字符,\1引用第一个分组,在此处引用的是前边匹配的整行,然后在行尾添加 END。
  • sed -r 's/[0-9][0-9]$/&.5/' datafile //&代表在查找串中匹配到的内容

  • sed -r 's/(Mar)got/\1ianne/g' datafile

  • sed 's/^/start /' learn_sed.txt 在每行行首添加start
  • sed 's/$/ end/' learn_sed.txt 在每行行尾添加end
  • sed '1,3s/^/#/' learn_sed.txt 在1到3行的行首添加#
  • sed -i '/second/s/22\.1/10.12/' myfile   #匹配second的行,把22.1替换成10.12由于.号有特殊意义所有需要转义  

  • sed -i '/second/s/#//' myfile       #匹配second的行,把#替换成空,即去掉#号,也一般用作去掉#注释  

  • sed -i 's/root/(&)/g' myfile        #把root用括号括起来,&表示引用前面匹配的字符  

w filename

写文本到一个文件,类似输出重定向 >

把正在用sed操作的文件内容写到另外一个文件中

  • sed 's/first/new first/w new.txt' learn_sed.txt
  • #w表示保存,new.txt文件名  
  • 执行该命令会将匹配行数据写入到新文件new.txt中

r filename

从另一个文件中读文本,类似输入重定向 <

读取一个文件到正在用sed操作的文件中

  从new2.txt中读取数据放在new.txt中的匹配行后

cat new.txt

  • new1
  • new2

cat new2.txt 

  • 222
  • 333

sed '/new1/r new2.txt' new.txt

  • new1
  • 222
  • 333
  • new2

sed '/new/r new2.txt' new.txt 

  • new1
  • 222
  • 333
  • new2
  • 222
  • 333

sed '1r new2.txt' new.txt

  • new1
  • 222
  • 333
  • new2

q

结束或退出sed

sed '5q' /etc/passwd#打印5行 

l

显示与八进制ACSII代码等价的控制符

 

{}

使用{}实现多项编辑,不同编辑命令之间用分号

sed -n '1,2{p;=}' learn_sed.txt/sed -n '1,2{=;p}' learn_sed.txt #两个编辑命令相互约束生效,行号只打印到了2

sed -n '1,3!{=;p}' learn_sed.txt #使用!对前边的匹配模式取反,注意!的位置

sed -n '/^first/!{/^$/!p}' learn_sed.txt #打印非first开头以及非空的行,先过滤出非first开头的行,然后在此基础上过滤出空行

sed '/root/{s/bash/nologin/;s/0/1/g}' test   #匹配root的行,把bash替换成nologin,且把0替换成1  

n

从另一个文件中读文本下一行,并从下一条命令而不是第一条命令开始对其的处理

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

sed -n '/line/{n;s/line/line22/p}' learn_sed.txt  输出为second line22\nlast line22,第一行与第三行被跳过

N

在数据流中添加下一行以创建用于处理的多行组

 

g

全局替换,当某行中有多个匹配项时,

  • 使用g可以全局匹配
  • 不使用g只匹配第一个
  • 使用2g会匹配第二个及第二个之后的匹配项
  • 使用2只匹配第二个
  • echo 'first line line line'|sed '/line/s/line/line22/' 输出为first line22 line line,只匹配了第一个
  • echo 'first line line line'|sed '/line/s/line/line22/g' 输出为first line22 line22 line22,全局匹配
  • echo 'first line line line'|sed '/line/s/line/line22/2g' 输出为first line line22 line22,匹配了第二个及以后的匹配项
  • echo 'first line line line'|sed '/line/s/line/line22/2' 输出为first line line22 line,只匹配了第二个

y

传送字符,替换单个字符,将字符替换为另一字符(不能对正则表达式使用y命令)

test_sed中的内容为:

  • 1234567890
  • 2345678901

执行sed 'y/1234567890/ABCDEFGHIJ/' test_sed的输出为:

  • ABCDEFGHIJ
  • BCDEFGHIJA

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

! 反向选择

sed -r '3!d' /etc/hosts

sed -n '/^first/!p' learn_sed.txt 打印非first开头的行,注意!的位置

     
     
文件内容 模式 举栗

cat learn_sed.txt 

first line

second line

three line

last line

x x为行号

sed '2p' learn_sed.txt (打印 文件中的第二行,因为sed默认打印文件中所有的行,所以第二行会打印两次)

sed -n '2p' learn_sed.txt (使用-n可以只打印匹配到的行)

x,y 表示行号从x到y

sed -n '1,3p' learn_sed.txt

/pattern 查询包含模式的行

sed -n '/first/p' learn_sed.txt (打印文件中能够匹配first字符的行)

 

/pattern/,/pattern 查询两个模式之间的行

sed -n '/first/,/three/p' learn_sed.txt(打印从包含first的行开始到包含three的行)

 

sed '/first/,/second/d' learn_sed.txt(删除从包含first的行到包含second的行)

sed '/second/,/first/d' learn_sed.txt(删除从包含second的行到包含first的行,由于first在second之后,所以会删除second之后的行)

 

/pattern/,x 打印匹配pattern的行到x行之间的行,若包含pattern在x行之后,则只打印匹配pattern的行

sed -n '/second/,3p' learn_sed.txt(打印文件中从匹配second的行到第3行)

  • second line
  • three line

sed -n '/second/,1p' learn_sed.txt(若包含second的行在第1行之后,则只打印匹配到second的行)

  • second line
 

x,/pattern/ 打印x行到匹配pattern的行之间的行,x行在包含pattern的行之后,则只打印x行到文件最后一行的数据

sed -n '1,/second/p' learn_sed.txt(打印文件中从1行到匹配到second的行)

  • first line
  • second line

sed -n '3,/second/p' learn_sed.txt(第3行在匹配到second的行之后,所以只打印了第3行之后的数据)

  • three line
  • last line
 

x,y!

查询不包含指定行号x和y的行

sed -n '1,3!p' learn_sed.txt(打印不包含第一行到第三行数据的行)

sed -n '1!p' learn_sed.txt(打印不包含第一行数据的行)

     

sed命令中引用变量

1.sed命令里面没有默认的变量时可以把单引号改成双引号

  • var=first
  • echo 'first line'|sed "s/$var/test/"  #输出为test line
  • echo 'first line'|sed 's/$var/test/'  #输出为first line ${var}没有被识别

2.sed命令里面有默认的变量时,sed里面的语句必须用单引

  • sed "$a test" learn_sed.txt  #会报错sed: can't find label for jump to `est'
  • sed '$a test' learn_sed.txt   #在文件行尾新增一行test

3.sed命令里面有默认的变量时,sed里面的语句必须用单引,自己定义的变量需要加单引号。

  • sed '$a '$var'' learn_sed.txt #正确使用
  • sed '$a $var' learn_sed.txt #自定义变量没有被识别,必须使用单引号将变量括起来才行

sed 中的多项编辑

1.使用多个-e对单个文件进行多项操作,多项编辑命令分别生效,多项命令的执行顺序对结果有影响。如果两个命令都是替换命令,那么第一个替换命令将影响第二个替换命令的结果。

  • sed -e '/^first/d' -e '/^$/d' learn_sed.txt 先删除以first开头的行,再删除空行
  • sed -e '/second/d' -e '/first/d' learn_sed.txt或者使用sed -r '/first|second/d' learn_sed.txt  删除包含second或first的行
  • sed -n -e '1,3p' -e '=' learn_sed.txt或者sed -n -e '=' -e '1,3p' learn_sed.txt  两个命令分别生效,打印行号时显示了4

2.使用{}实现多项编辑,不同编辑命令之间用分号

  • sed -n '/^first/!{/^$/!p}' learn_sed.txt #打印非first开头以及非空的行
  • sed '{/first/d;/second/d}' learn_sed.txt  删除包含second或first的行
  • sed -n '1,2{p;=}' learn_sed.txt/sed -n '1,2{=;p}' learn_sed.txt #两个编辑命令相互约束生效,行号只打印到了2
  • sed -n '1,3!{=;p}' learn_sed.txt #使用!对前边的匹配模式取反,注意!的位置

3.多项编辑直接用分号分割

  • sed -r '1,3d; s/Hemenway/Jones/' datafile
  • sed -r '2s/WE/1000phone/g; 2s/Gray/YYY/g' datafile 等同于sed -r '2{s/WE/1000phone/g; s/Gray/YYY/g}' datafile

2)使用正则表达式、扩展正则表达式(必须结合-r选项)

^

匹配行首符合条件的内容,用法格式"^pattern"

  • #######sed的匹配模式支持正则表达式#####################  
  • sed -n '/r*t/p' /etc/passwd#打印匹配r有0个或者多个,后接一个t字符的行  
  • sed -n  '/.r.*/p' /etc/passwd#打印匹配有r的行并且r后面跟任意字符  
  • sed -n '/o*/p' /etc/passwd#打印o字符重复任意次  
  • sed -n '/o\{1,\}/p' /etc/passwd#打印o字重复出现一次以上  
  • sed -n '/o\{1,3\}/p' /etc/passwd#打印o字重复出现一次到三次之间以上  

$

匹配行尾符合条件的内容,用法格式"pattern$"

^$

空白行

.

匹配任意单个字符

*

匹配紧挨在前面的字符任意次(0,1,多次)

.*

匹配任意长度的任意字符

\?

匹配紧挨在前面的字符0次或1次

 

\{m,n\}

匹配其前面的字符至少m次,至多n次

 

\{m,\}

匹配其前面的字符至少m次

 

\{m\}

精确匹配前面的m次\{0,n\}:0到n次

 

\<

锚点词首----相当于 \b,用法格式:\<pattern

 

\>

锚点词尾,用法格式:\>pattern

 

\<pattern\>

单词锚点

 
 

分组,用法格式:pattern,引用\1,\2

 

[]

匹配指定范围内的任意单个字符

 

[^]

匹配指定范围外的任意单个字符

 

[:digit:]

所有数字, 相当于0-9, [0-9]---> [[:digit:]]

 

[:lower:]

所有的小写字母

 

[:upper:]

所有的大写字母

 

[:alpha:]

所有的字母

 

[:alnum:]

相当于0-9a-zA-Z

 

[:space:]

空白字符

 

[:punct:]

所有标点符号

 

sed的经典例子及常用操作

1.cat file.txt的输出如下,期望处理以下文件内容,将域名取出并进行计数排序 

内容如下:

期望结果如下,输出内容为域名的出现的次数 域名:  

实现方式:

  • cat file.txt | sed -e ' s/http:\/\///' -e ' s/\/.*//' | sort | uniq -c | sort -rn  
  • awk -F/ '{print $3}' file.txt |sort -r|uniq -c|awk '{print $1"\t",$2}'  

2.用grep结合sed取出网卡的ip地址  

 ifconfig | grep -B1 "inet addr" |grep -v "\-\-" |sed -n -e 'N;s/eth[09].*\n.*addr:[09]{1,3}\.[09]{1,3}\.[09]{1,3}\.[09]{1,3}.*/\1 \2/p'  

3.批量替换多个文件中的字符串 

sed -i "s/原字符串/新字符串/g" `grep 原字符串 -rl 所在目录`

其中,-i 表示inplace edit,就地修改文件,-r 表示搜索子目录,-l 表示输出匹配的文件名,这个命令组合很强大,要注意备份文件。

4.替换命令中的注意点

  • $ sed 's/test/mytest/g' example  在整行范围内把test替换为mytest。如果没有g标记,则只有每行第一个匹配的test被替换成mytest。
  • $ sed -n 's/^test/mytest/p' example  (-n)选项和p标志一起使用表示只打印那些发生替换的行。也就是说,如果某一行开头的test被替换成mytest,就打印它。
  • $ sed 's/^192.168.0.1/&localhost/'example  &符号表示替换换字符串中被找到的部份。所有以192.168.0.1开头的行都会被替换成它自已加localhost,变成192.168.0.1localhost。
  • $ sed -n 's/\(love\)able/\1rs/p' example  love被标记为1,所有loveable会被替换成lovers,而且替换的行会被打印出来。
  • $ sed 's#10#100#g' example  不论什么字符,紧跟着s命令的都被认为是新的分隔符,所以,“#”在这里是分隔符,代替了默认的“/”分隔符。表示把所有10替换成100。

5.使用|同时匹配两种模式

  • sed -r '/first|second/d' learn_sed.txt或者sed -nr '/first|second/p' learn_sed.txt
  • sed -nr '/^(patt1|patt2)$/p'  匹配整条行
  • sed -n '/^\(patt1\|patt2\)$/p' 也可以删除-r并添加转义符

扩展知识:

  • Ubuntu:sed -i '2d' test.txt
  • Mac:sed -i '' '3d' test.txt    Mac中必须使用'',否则报错sed: 1: "test.txt": undefined laebl 'est.txt',原因是mac强制要求备份,使用''可以只保留一份
  • 使用&表示替换字符串 sed 's/a/&i/' aaa.txt ,将每行第一个被匹配到的a都被替换为ai
  • 紧挨着s命令的符号被认为是分割符 sed 's#a#i#' aaa.txt 分割符为#

参考:

猜你喜欢

转载自www.cnblogs.com/mianbaoshu/p/12067409.html