Linux 文本修正工具sed的使用

何为sed

sed是Stream Editor的简称,是Linux自带的一个文本处理工具,以行为单位,对文本进行处理,可以对每行的内容做替换、删除、新增、选取等操作。

sed在处理文本时,会把当前行读入到缓冲区,这个缓冲区称为模版块(Pattern Space),然后用相关命令处理模板块的内容,处理完成后,将缓冲区的内容输出,直到文件末尾。此外sed也提供了临时缓冲区(Hold Space),用于实现更加复杂的文本操作。

sed命令行格式为:

sed [option]... {script-only-if-no-other-script} [input-file]...

option为选项,后面接命令,再后面接输入文件。

命令

sed单个命令的语法为:

[n1[,n2]]<function>

n1n2可选,代表选择进行function操作的前置条件,n1n2有多种取值方式:

  • 当取值为数字或$时,代表行号的限定范围,$表示最后一行,例如:
    从第10行开始,进行function操作,直到第20行,那么可以写为:10,20<function>
    从第10行开始,进行function操作,可以写为:10<function>10,$<function>
    从第1行开始,进行function操作,直到第10行,可以写为:1,10
  • 当取值为正则表达式时,代表行需要满足正则表达式才会进行function的相关操作,例如:
    从第10行开始,对不以Hello开头的行进行function操作,可以写为10,/^Hello/<function>
  • 当取值为包含!时,表示在一定条件下不执行相关操作,例如:
    不对第1到4行的文本执行function操作,可以写为:1,5!<function>

此外sed可以接受多个命令,可以用;隔开,或者用多个-e选项即可,在处理模版块时会按照先后依次顺序执行。

在介绍function之前,为了方便演示,可以新建一个文件testfile,并写入以下内容:

Line 1
Line 2
...
Line 10

或者使用Shell自动生成:

echo > testfile
for i in {1..10}
do
	echo "Line $i" >> testfile
done
基本function的种类:
  • a:在当前行下面插入文本。
    后面可以接字符串,这个字符串会插入到当前行的下一行,例如在第8行后插入字符串helloworld

    sed '8ahelloworld' testfile
    

    或者从第8行开始,在每行后面插入一个helloworld

    sed '8,$a helloworld'
  • i:在当前行上面插入文本
    类似于a,后面接字符串,这个字符串会插入到当前行的上一行,例如在第8行之前插入字符串helloworld

    sed '8ihelloworld' testfile
    
  • c:把当前的行替换为新的文本
    例如把第八行的Line 8替换为helloworld

    sed '8chelloworld' testfile
    
  • d:删除当前的行
    例如删除第八行的文本Line 8删除:

    sed '8d' testfile
    

    或者删除第5到第8行文本:

    sed '5,8d' testfile
    

    删除包含字符串Line 8的行:

    sed '/Line 8/d' testfile
    
  • s:替换指定的字符串,语法规则如下:

    sed 's/Regexp/Replacement/Flags' file
    

    s命令将符合正则表达式Regexp的行全部替换成Replacement,最后的字符Flags为标志选项,有以下几种:

    1. g:用Replacement替换模版空间中所有匹配Regexp的部分,则不仅仅是第一个匹配部分
      例如要将testfile中的单词Line全部替换成Word,那么可以写作:
      sed 's/Line/Word/g' testfile
      
    2. 1到9的数字N:只用Replacement替换模版空间中,忽略第0N - 1个匹配Regexp的部分,然后将匹配Regexp的部分输出。
      例如,下面案例会将Line替换为Lixx
      sed 's/[a-z]/x/2g' testfile
      
    3. p:若发生了替换操作,则输出模版空间中修改后的行数据,和p命令很类似
    4. w file-path:若发生了替换操作,将模板块中的数据写入到文件file-path
      例如下面示例会将从第5行开始,替换LineWord,并将替换后的结果输出到当前目录的outputfile文件,直到文件末尾:
      sed -n '5,$s/Line/Word/gw outputfile' testfile
      
    5. i:与Regexp匹配时,不区分大小写
      例如,下面命令可以将Line替换成Word
      sed 's/line/Word/ig' testfile
      

    此外,也可利用s在每行头部或者尾部添加字符串,可以利用字符^表示行头,字符$表示行尾
    比如在每行行头添加单词Hello

    sed 's/^/Hello/g' testfile
    

    在行尾添加单词Hello

    sed 's/$/Hello/g' testfile
    

    当然s前面也可以加上行范围

  • p:打印当前模板块空间的所有内容(模板块的定义前面已经提到),并追加到默认输出之后
    例如在每行后面追加一个单词number,并将修改前和修改后的结果打印出来(-n表示不打印默认输出):

    sed -n 'p;s/$/number/g;p' testfile
    

    或者从第8行开始,将以Line开头的行打印出来

    sed '5,/Line/p' testfile
    
其他function种类:
  • n:读取下一个输入行,用下一个命令处理新的行而不是使用第一个命令

  • N:追加下一个输入行到模板块的后面并在中间嵌入一个新行,可以利用该命令将多个行的内容整合为一行。
    例如下列命令可以将三行语句整合为一行:

    sed 'N;N;s/\n/ /g' testfile 
    

    逻辑就是就是读取三行后,然后将换行符\n替换为空格。
    或者可以输出行号为奇数的行:

    sed -n '$!N;P' testfile
    
  • P:打印当前模板块空间的第一行

模板块和临时缓冲区(Hold Space)的操作:

  • h:拷贝模板块的内容到临时缓冲区
  • H:追加模板块的内容到临时缓冲区
  • D:删除模板块的第一行(意味着这个被删除的部分不会传至标准输出),并放弃之后的命令,然后对新读入的内容,重头执行sed
  • g:取得临时缓冲区的内容,并替换当前模板块中的文本
  • G:取得临时缓冲区的内容,并追加到当前模板块中文本的后面

可以利用sed的临时缓冲区执行更加复杂的文本修改操作,举一个经典的例子:

实现倒序输出,即从最后一行开始逐行输出到第一行
思路:要实现倒序输出,我们需要在读取每一行的时候,就将行的内容放在模板块的前面。所以在读第一行的时候,需要将第一行的文本从模式块读到临时缓冲区,然后再读第二行的时候,把临时缓冲区中第一行的数据追加到模版块,依次类推。只需要对第一行和最后一行的做特殊处理即可。

	sed '1!G;h;$!d' testfile

1!G表示不对第一行做G操作,$!d表示不对最后一行做d操作
执行过程示例图:
在这里插入图片描述

其他操作:

  • I:列出不能打印字符的清单
  • q:退出sed
选项

option参数主要包含以下几个:

  • -n--quiet--silent:仅显示被sed特殊处理的行,如果不加,那么所有来自输入文本的数据都会被输出,不论有没有进行过修改。
  • -e <script>--expression=<script>:使用script,也可以省略掉-e
  • -f <script-file>--file=script-file:指定存放script的文件
  • -i[suffix]--in-place[=suffix]:如果不加suffix,那么直接修改文件的内容,不输出到终端。如果加了suffix,则会在处理前,对文件进行备份(复制),备份文件名会在原先文件名后面加上suffix,然后再对原文件进行修改
  • -l <number>--line-length=<number>
  • --posix:禁用的GNU扩展功能,例如replacement选项中中的\L\l\U\u\E
  • -r--regexp-extended:让sed支持扩展的正则表达式
  • -s--separate:在处理多个文件时,对它们依次单独处理,而不是视为一个整体
  • -u--unbuffered:从输入文件中加载尽可能少的行,并更频繁地刷新输出缓冲区,适合机器内存比较紧张的情况
  • -z--null-data:每行按照\0分隔,而不是换行符。
  • --help:查看sed帮助
  • --version:查看sed版本
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值