linux小记:恍然大明白,sed命令中[commands]的格式

原创 2016年06月05日 21:39:55

sed是我在linux上最喜欢的命令之一!(其实我很想说sed说是我最喜欢的命令,不过linux我喜欢的逆天的命令实在是太多了,所以sed就是其中“之一”了吧。)

之前一直觉得sed的格式乱乱的,又是sed '1,2p' fileName,又是sed 's/old/new/g' fileName的,格式千差万别,毫无规律可循!直到今天看到了这篇文章,终于看到了统一点!

sed的用法就是:

sed [options] [commands] [input-file]

options就是带杠的参数,input-file就是文件的名字,关键在于commands!

不过commands也是有固定格式的:

[范围][指令]

关键在于[range]和[command]格式都比较丰富,所以组合起来才显得比较乱。

范围

先来说说范围!

最简单的范围莫过于——
‘m,n’表示从m行到n行: sed '2,3p' fileName,指处理2~3行;
‘m,+n’表示从m行到m+n行: sed '2,+3p' fileName,指处理2~(2+3=5)行。
‘m~n’表示从m行开始每n行匹配一次: 如1~2表示只匹配奇数行,2~2表示只匹配偶数行。
特殊符号包括:$表示最后一行;0表示第一行前,也就是最开始;匹配后加!表示不匹配以上条件的行(类似取反)。如sed '1~2d' file #删除奇数行sed '1~2!d' file #删除偶数行

复杂一点的范围——
使用正则表达式匹配范围:'3,/hello/'指的是从第3行到第一次出现hello的行的这一部分。比如sed '3,/hello/d' fileName指删除3~”第一次出现hello的行”。sed -n '/test/,/check/p' fileName指打印test到check的行。

正式因为这些匹配的方式多样,导致他们和命令组合起来之后显得比较多变。

指令

比较简单的指令也比较好看懂——
比如d,和前面的范围组合起来之后,简单的就是sed '2,5d' fileName,删除2~5行;稍复杂点儿就是sed '2,/hello/d',删除2~“第一次出现hello的行”。

复杂的指令和之前的范围组合起来就不容易看懂了——
比如ss是个自带一大串参数的指令,也是用的最多的指令。其格式为s/oldString/newString/flags,那么和前面的范围组合起来就把commands这一块儿变成了:[range]s/oldString/newString/[flags]
这样的话整个sed命令就变成了:

sed [options] '[range]s/oldString/newString/[flags]' [filename]

比如sed '2,$s/hi/hello/g' fileName表示从第二行到最后一行,将所有的hi替换成hello。

如果[范围]再复杂一点儿,变成sed '2,/haha/s/hi/hello/g' fileName,表示从第二行到第一次出现haha的行,将所有的hi替换为hello;sed '/haha/s/hi/hello/g'表示将所有含有haha的行的所有hi替换为hello。

这样只要知道sed命令中间的commands部分由范围和指令组成,在分别搞懂了这两部分的形式,他们再组合起来就不显得混乱了。

一些知识点

-ibak

sed的-i命令是覆盖源文件,以后建议使用-ibak,比如sed '2,+8d' hello.txt,在删除hello.txt文件的2~10行之前,会先生成一个名为hello.txtbak的备份文件,有备份总是好事儿,大不了再手动删一次,总比sed命令改坏了源文件欲哭无泪强!

-np

p一般都是和-n同时出现,可以起到只显示被处理的行的效果。
比如,对于DreamList.puppy文件,原内容为:

lgl@pArch ~/tmp/sed $ cat DreamList.puppy 
Drm Lst wth Pppy
- S th srs
- Slf-stdy  MB
- Tk phts rd MB
- St sd th lk f r rd d tlk dr sst
- t brkfst vry dy, lch vry dy, dr vry dy
- R  th plyrd d Strtch th bds ftr tht
- Wtch mvs
- Wt tsd th rl's drmtry
-  t hr wrkplc t wt hr t ff dty
- Rd tsd th cmps
- Wtch xhbts sh hs trsts 
- Sy  LV Y vry dy vry mmt
- t FST, FST, FST f r w
- Mk ... r... Prdc LV

进行替换处理,将所有出现S的行的小横杠换成五个#:

lgl@pArch ~/tmp/sed $ sed '/S/s/-/#####/g' DreamList.puppy    
Drm Lst wth Pppy
##### S th srs
##### Slf#####stdy  MB
- Tk phts rd MB
##### St sd th lk f r rd d tlk dr sst
- t brkfst vry dy, lch vry dy, dr vry dy
##### R  th plyrd d Strtch th bds ftr tht
- Wtch mvs
- Wt tsd th rl's drmtry
-  t hr wrkplc t wt hr t ff dty
- Rd tsd th cmps
- Wtch xhbts sh hs trsts 
##### Sy  LV Y vry dy vry mmt
##### t FST, FST, FST f r w
- Mk ... r... Prdc LV

可以看到不管处理没处理的行都打印出来了。
如果使用p-n的组合:

lgl@pArch ~/tmp/sed $ sed -n '/S/s/-/#####/gp' DreamList.puppy
##### S th srs
##### Slf#####stdy  MB
##### St sd th lk f r rd d tlk dr sst
##### R  th plyrd d Strtch th bds ftr tht
##### Sy  LV Y vry dy vry mmt
##### t FST, FST, FST f r w

可以看到只有被处理的行被显示了。

命令和flags

刚刚说到s命令最后可以有flags,其中flags和命令很多都是一模一样的。这里提一下防止搞晕。
例如:
sed '2,3p' fileName为打印2~3行,这里的p是和s同级别的命令。
sed '2,3s/hi/hello/gp',这里的p属于s命令的flags,是s命令的一部分。

连续使用sed

连续使用sed命令需要使用-e参数:

sed -e [command1] -e [commaned2]... [inputfile]

sed -i -e G -e 's/^-/#####/g' fileName为先在每一行后面添加空行,再将所有开头的’-‘替换为’#####’。

其实连续使用sed还可以使用;。以上命令等价于:
sed -i '{G;s/^-/#####/g}' fileName或者sed -i 'G;s/^-/#####/g' fileName

奇偶行与n

上面我们说范围匹配的时候提到过奇偶行。
sed '1~2d' file #删除奇数行
sed '1~2!d' file #删除偶数行
sed '2~2d' file #删除偶数行

也可以用n(不是-n)实现同样的效果:
sed 'n;d' file删除偶数行
sed '1d;n;d' file删除奇数行

缓冲区

想明白上面的nG的用法,需要涉及到缓冲区。

sed处理问本行的步骤:

  • 读取一行到模式空间缓冲区
  • 按照命令对模式空间缓冲区内容进行处理
  • 打印处理后缓冲区中的文本
  • 循环到第一步读取下一行,直到文本处理完

临时缓冲区、n

每一行都被保存在一个叫模式空间的临时缓冲区中,除非行被删除或者输出被取消,否则所有被处理的行都将打印在屏幕上,接着模式空间被清空。

所以sed 'n;d' file删除偶数行,可以解释为:sed开始读了第一行到缓冲区,然后执行n,意味再读一行,所以就读了第二行,然后执行d,于是第二行被删除了。以此类推,所有的偶数行都被删除了。

n N Read/append the next line of input into the pattern space.

保持缓冲区、hG

hg是互逆的过程,其中消协代表拷贝,大写代表添加。

h H Copy/append pattern space to hold space.
g G Copy/append hold space to pattern space.

我们先来看一个命令:
sed -e '/test/h' -e '$G' file
在这个例子里,匹配test的行被找到后,将存入模式空间(临时缓冲区),h命令将其复制并存入一个称为保持缓存区的特殊缓冲区内,保持缓冲区如果不使用G取出,将会一直存在(所以叫“保持”缓冲区,而不是“临时”缓冲区)。

第二条语句的意思是,当到达最后一行后,G命令取出保持缓冲区的行,然后把它放回模式空间中,且追加到现在已经存在于模式空间中的行的末尾。在这个例子中就是追加到最后一行。简单来说,任何包含test的行都被复制并追加到该文件的末尾。

看了这我们就知道为什么sed G fileName能够在每一行后面添加一个空行了。因为保持缓冲区中没有内容,G就只能取到空内容。每次sed取一行文本到临时缓冲区,G就在保持缓冲区中取空内容添加到这一行后面,也就是在这行后面添加了一个空行,以此类推,所有行后面都被追加了一个空行。

x

x Exchange the contents of the hold and pattern spaces.

这个时候我们再看x命令就不难理解了。x表示互换临时缓冲区和保持缓冲区的内容。

所以看这个命令:

lgl@pArch ~ $ seq 3
1
2
3
lgl@pArch ~ $ seq 5 | sed 'x'

1
2
3
4
lgl@pArch ~ $ 

刚开始hold space是空的,1和空行交换,1进入了hold space,空行进入了pattern space,输出空行,接下来1和2交换,2进入hold space,1换到了pattern space,输出。一直到最后,5被换如了hold space。所以只打印了空行和1~4。

版权声明:本文为博主原创文章,未经博主允许不得转载。

Use multiple CPU Cores with your Linux commands — awk, sed, bzip2, grep, wc, etc.

前言 Here’s a  common problem:  You ever want to add up a very large list (hundreds of megab...

Linux sed Commands

1. Sed简介 sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处理完成...

[Python] 利用commands模块执行Linux shell命令

用Python写运维脚本时,经常需要执行linux shell的命令,Python中的commands模块专门用于调用Linux shell命令,并返回状态和结果,下面是commands模块的3个主要...

30 Useful Linux Commands for System Administrators【很基础的命令】

In this article we are going to review some of the useful and frequently used Linux or Unixcommands ...
  • Viidiot
  • Viidiot
  • 2013年09月22日 08:38
  • 815

《A Practical Guide to Linux Commands, Editors, and Shell Programming》之命令行解析

在我的博文《Linux Shell Scripting Cookbook》Linux常用命令笔记(三)备注【2】中曾提及 命令行的解析,今天看《A Practical Guide to Linux C...

30 Useful Linux Commands for System Administrators(这些命令均可以在centos服务器上运行)

1. Uptime Command In Linux uptime command shows since how long your system is running and the numbe...

linux命令中Sed各种使用方式

  • 2017年03月03日 10:13
  • 18KB
  • 下载

批量替换文本内容 linux sed命令

1.1. Sed简介 2.sed 是一种在线编辑器,它一次处理一行内容。处理时,把当前处理的行存储在临时缓冲区中,称为“模式空间”(pattern space),接着用sed命令处理缓冲区中的内容,处...

linux script 好用的sed命令

  • 2008年06月14日 22:38
  • 166KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:linux小记:恍然大明白,sed命令中[commands]的格式
举报原因:
原因补充:

(最多只允许输入30个字)