文本处理三剑客之sed

文本处理三剑客之sed个人博客地址 http www pojun tech 欢迎访问 本文部分示例引用自 http www gnu org software sed manual sed html 这是 sed 的官方帮助手册 如果想查看完整示例 可移步此网址 查看 sed 的详细介绍 sed 简介

大家好,我是讯享网,很高兴认识大家。

个人博客地址:http://www.pojun.tech/ 欢迎访问

   本文部分示例引用自 http://www.gnu.org/software/sed/manual/sed.html 。这是sed的官方帮助手册,如果想查看完整示例,可移步此网址,查看sed的详细介绍。

sed 简介

   sed 命令通常用于以下几个场景
- 编辑比较大的文本文件
- 编辑命令太复杂,交互式文本编辑器中不好操作
- 简化对文件的反复操作,编写转换程序

简单的示例

   首先我们先来看一个示例,在这个示例中,我们将使用sed 来完成一些简单的事情,其中具体的语法细节会在后面的内容中详细讲解,这里就先演示以下sed的强大魅力。

下面的演示将以这段文本作为基础

[root@localhost sed]#cat sedtest I have a pen, I have an apple. (Uhh~)Apple-pen! I have a pen, I have pineapple. (Uhh~)Pineapple-pen! Apple-pen~Pineapple-pen(Uhh\h~) Pen-Pineapple-Apple-pen! Pen-Pineapple-Apple-pen! 

讯享网

我们在每行的开头加上一个 # 号,也就是将每一行都注释掉

讯享网[root@localhost sed]#sed 's/^/#/g' sedtest #I have a pen, # I have an apple. #(Uhh~)Apple-pen! #I have a pen, # I have pineapple. #(Uhh~)Pineapple-pen! #Apple-pen~Pineapple-pen(Uhh\h~) # Pen-Pineapple-Apple-pen! #Pen-Pineapple-Apple-pen! 

当然,我们也可以轻松地在每一行的结尾加上我们喜欢的字符 $ ,请先不要疑惑,如果对正则表达式不是很理解的朋友可以这样来理解,第一个$表示的是行尾,第二个 $ 表示将要准备替换为的字符。详细的内容我们会在接下来介绍。

 [root@localhost sed]#sed 's/$/$/g' sedtest  I have a pen,$  I have an apple.$ (Uhh~)Apple-pen!$ I have a pen,$  I have pineapple.$ (Uhh~)Pineapple-pen!$ Apple-pen~Pineapple-pen(Uhh\h~)$  Pen-Pineapple-Apple-pen!$ Pen-Pineapple-Apple-pen!$ 

我们在文本的第一行之前插入一行,I have an orange

讯享网[root@localhost sed]#sed '1 i I have an orange' sedtest I have an orange I have a pen, I have an apple. (Uhh~)Apple-pen! I have a pen, I have pineapple. (Uhh~)Pineapple-pen! Apple-pen~Pineapple-pen(Uhh\h~) Pen-Pineapple-Apple-pen! Pen-Pineapple-Apple-pen! 

当然啦,能增加肯定就可以删除了,所以接下来我们将文本中所有包含 pen 字眼的行删掉。

[root@localhost sed]#sed '/pen/d' sedtest I have an apple. I have pineapple. 

注意: 我们在实例中进行的所有操作,并没有真正的改变原文本文件的内容,只是在输出的内容有了变化,这一点我们将会进行介绍。

sed 的用法

sed 是一个强大的工具,通过之前的示例,我们可以看出,sed可以实现很多的功能,实际上它也是结合了正则表达式来完成的所有的操作,这一点与grep很相似。因此,如果想要使用好sed 这把利器,掌握好正则表达式是非常有必要的。关于正则表达式的使用,在我之前的一片博客中已经有了详细的介绍,《Linux 基础命令(五)—— 文本处理三剑客之grep》,可以参照这篇博客去了解详细的使用。下面的介绍中,我们将不再赘述正则,而是直接使用。

sed 命令的常用用法如下

讯享网 sed [option]... [SCRIPT] [INPUTFILE ...] 

常用的命令行选项 OPTIONS

与许多命令一样,sed命令也有着众多繁而复杂的选项,合理的使用这些选项会产生意想不到的效果。下面介绍一些常用的选项。

 -n, --quiet, --silent 默认情况下,sed命令会将它处理的每一行的内容打印到标准输出,使用这个选项可以禁止输出。 -e script 将脚本添加到命令中执行。可以理解为多点编辑。就是使用 -e 选项 加上脚本内容 ,可以使sed命令实现一个命令,匹配多个脚本,比如 sed -e '/pen/d' -e 's/$/$/g' sedtest -f script-file 从指定的脚本文件中,读取出脚本内容,并合并到sed COMMAND中进行执行。通俗的理解为将 脚本写在了文件中。 -r 支持扩展的正则表达式,与egrep一样,扩展的正则表达式更利于阅读,没有那么多的斜杠,利于书写。 -i 直接修改源文件。如果在命令中加入了 -i 选项,源文件的内容将会被直接修改掉。 -i[SUFFIX] 这还是-i 选项,这个选项的意思是说,如果在使用 该选项的过程中指定了后缀名称,那么该命令在执行的过程中会先将源文件备份成以[SUFFIX] 为后缀的文件,然后对文件进行操作 

接下来,我们还是以文章开头提到的文件来进行测试,来解释这些选项的含义。

  • 将文本中所有包含 pen 字样的行删除掉,同时将 apple 字样替换成 orange
讯享网[root@localhost sed]#sed -e '/pen/d' -e 's/apple/orange/g' sedtest I have an orange. I have pineorange. 
  • 创建脚本文件 scritp1 并在里面写入 脚本 。
 #在script1 文件中写入符合正则表达式的脚本 [root@localhost sed]#echo "/pen/d" &> script1 #查看脚本文件内容 [root@localhost sed]#cat script1  /pen/d #执行sed命令 [root@localhost sed]#sed -f script1 sedtest  I have an apple. I have pineapple. 

这种以读取脚本文件来处理文本文件的方式,很适合我们在处理复杂文件的时候使用,实际生产中,我们往往会遇到大量的复杂的文本文件需要进行处理,sed命令可以很好的解决。例如日常大量的日志。

讯享网#在使用-i 选项的同时,指定备份的后缀名称 [root@localhost sed]#sed -i.bak -f script1 sedtest  #列举出当前列表下的文件 [root@localhost sed]#ll total 12 -rw-r--r--. 1 root root 7 Aug 11 21:03 script1 -rw-r--r--. 1 root root 37 Aug 11 21:08 sedtest -rw-r--r--. 1 root root 188 Aug 11 20:02 sedtest.bak #查看修改后的文件 [root@localhost sed]#cat sedtest I have an apple. I have pineapple. #查看备份文件 [root@localhost sed]#cat sedtest.bak  I have a pen, I have an apple. (Uhh~)Apple-pen! I have a pen, I have pineapple. (Uhh~)Pineapple-pen! Apple-pen~Pineapple-pen(Uhh\h~) Pen-Pineapple-Apple-pen! Pen-Pineapple-Apple-pen! 

我们前面曾经介绍过,sed 命令的执行结果默认是不会修改源文件,而是直接输出到标准输出的。接下来,我们将处理后的结果保存到一个新的文件中。

  • 不使用 -i 选项,将修改后的文本保存到另外一个文件中。
#使用IO重定向 轻松实现文件另存为 [root@localhost sed]#sed '/pen/d' sedtest &> sedtest2 [root@localhost sed]#ll total 16 -rw-r--r--. 1 root root 7 Aug 11 21:03 script1 -rw-r--r--. 1 root root 188 Aug 11 20:02 sedtest -rw-r--r--. 1 root root 37 Aug 11 21:25 sedtest2 [root@localhost sed]#cat sedtest2 I have an apple. I have pineapple. 

当然,在实际使用中,我们通常是会直接修改源文件的,这样的话,直接使用相应的选项就可以了。


讯享网

sed 脚本概述

在前面的例子中,我们已经见识到了sed 命令结合正则表达式脚本 所产生的强大的效果。sed命令的脚本其实是比较复杂的,它不光可以写正则表达式,更可以使用地址定界+命令选项的方式来实现我们想要实现的功能。
在sed中,我们将正则表达式也看作一种地址定界

脚本的书写格式是 * ‘地址命令’*

sed命令中支持的地址定界

定界类型 作用
不给地址 对全文进行处理
# 指定的行
/pattern/ 能够被模式匹配到的每一行
#,# 从第n行到第m行
#,+# 从第n行,加上其后面m行
/pat1/,/pat2/ 符合第一个模式和第二个模式的所有行
#,/pat1/ 从第n行到符合 /pat1/ 这个模式的行
1~2 ~ 这个符号表示步进,1~2 表示的是奇数行
2~2 2~2 表示的是偶数行

sed 命令中常用的编辑命令

定界类型 作用
d 删除模式空间匹配的行,并立即启用下一轮循环
p 打印当前模式空间内容,追加到默认输出之后
q 读取到指定行之后退出
a [\]text 在指定行后面追加文本,支持使用\n实现多行追加
i [\]text 在行前面插入文本
c [\]text 替换行为单行或多行文本
w /path/somefile 保存模式匹配的行至指定文件
r /path/somefile 读取指定文件的文本至模式空间中匹配到的行后
= 为模式空间中的行打印行号
! 模式空间中匹配行取反处理

下面我们使用几个简单的示例来演示这些常用选项的使用。

  • 读取到第二行的时候退出命令
讯享网[root@localhost sed]#seq 3 | sed '2q' 1 2 
  • 打印第2行到第5行数据
[root@localhost sed]#seq 10 | sed -n '2,5p' 2 3 4 5 
  • 在第2行后面插入“hello”
讯享网 [root@localhost sed]#seq 3 | sed '2ahello' 1 2 hello 3 [root@localhost sed]#seq 3 | sed '2a\hello' 1 2 hello 3 
  • 在sedtest这个文本文件中,在所有apple 字样前面加入“Hello World”
 [root@localhost sed]#sed '/apple/i\Hello World' sedtest I have a pen, Hello World I have an apple. (Uhh~)Apple-pen! I have a pen, Hello World I have pineapple. Hello World (Uhh~)Pineapple-pen! Hello World Apple-pen~Pineapple-pen(Uhh\h~) Hello World Pen-Pineapple-Apple-pen! Hello World Pen-Pineapple-Apple-pen! 

使用 s/// 查找替换

使用 s/// 查找替换实际上也是sed 脚本的一部分,在vim中也有相应的使用。支持使用其他的分隔符s@@@,s。
常用的有如下的替换标记:
- g: 行内全局替换
- p: 显示替换成功的行
- w /PATH/TO/SOMEFILE:将替换成功的行保存至文件中

下面实现一个特殊的示例,在所有的apple单词后面加上Hello,在所有的pen单词前面加上World

讯享网 [root@localhost sed]#sed -e 's/apple/&Hello/g' -e 's/pen/World&/g' sedtest I have a Worldpen, I have an appleHello. (Uhh~)Apple-Worldpen! I have a Worldpen, I have pineappleHello. (Uhh~)PineappleHello-Worldpen! Apple-Worldpen~PineappleHello-Worldpen(Uhh\h~) Pen-PineappleHello-Apple-Worldpen! Pen-PineappleHello-Apple-Worldpen! 

示例中的 & 符号可以理解为前一个 模式 &的位置,就是配置之后前一个模式的的位置。

这个示例还可以有另外一种实现方式,就是使用正则表达式的分组功能。

 #使用正则表达式式的分组功能,可以实现同样的功能 [root@localhost sed]#sed -e 's/\(apple\)/\1Hello/g' -e 's/\(pen\)/World\1/g' sedtest #也可以使用扩展的正则表达式 [root@localhost sed]#sed -r -e 's/(apple)/\1Hello/g' -e 's/(pen)/World\1/g' sedtest 

s/// 替换命令的使用方式还可以很灵活,可以分别指定让哪些行进行匹配,使用的时候可以灵活应对。

将第1行至第5行的apple字样替换为HELLO,将每一行的第二个en单词替换成EN,第一个不理会

讯享网 # s///替换命令可以写在一个脚本里面 [root@localhost sed]#sed "2,5s/apple/Hello/g; s/en/EN/2g" sedtest I have a pen, I have an Hello. (Uhh~)Apple-pen! I have a pen, I have pineHello. (Uhh~)Pineapple-pen! Apple-pen~Pineapple-pEN(Uhh\h~) Pen-Pineapple-Apple-pEN! Pen-Pineapple-Apple-pEN! 

高级编辑命令以及模式空间和保持空间

我们前面已经介绍了很多关于sed命令的使用,在实际的使用中,这些命令的组合基本上可以完成大部分的日常工作。sed本身其实还有还多其他的高级编辑命令和使用方式,这就是接下来要介绍的内容。

模式空间和保持空间

sed模式空间和保持空间

高级命令使用

命令 命令作用
   D    从模式空间中删除行直到第一个换行符,然后重新启动循环。如果模式空间包含换行符,则删除直到第一个换行符的模式空间中的文本,并不会读取新的输入行,而使用合成的模式空间重新启动循环。如果模式空间不包含换行符,则会像发出d命令那样启动正常的新循环
G 将行从保持空间追加到模式空间,并在其前面加上一个换行符。
H 将模式空间的行附加到保持空间,并在其前面加上换行符。
N 读取匹配到的行的下一行追加至模式空间。
P 打印模式空间开端至\n内容,并追加到默认输出之前
d 删除模式空间中的行
g 从保持空间取出数据覆盖(替换)至模式空间
h 把模式空间中的内容覆盖(替换)至保持空间中
l 以明确的形式打印模式空间的内容,每行的末尾都会标有$
n 读取匹配到的行的下一行覆盖至模式空间
x 把模式空间中的内容与保持空间中的内容进行互换

下面的示例很好的说明了N,D的使用

 [root@localhost sed]# seq 6 | sed -n 'N; l; D' 1\n2$ 2\n3$ 3\n4$ 4\n5$ 5\n6$ 
  1. l 命令能够明确的打印模式空间里面的内容
  2. sed 首先将第一行读入模式空间(即“1”)。
  3. 在每个循环开始时,N 命令将附加一个换行符和下一行到模式空间(即’1’,’\ n’,’2’在第一个周期)。
  4. D命令将模式空间中第一个\n以及之前的内容全部删除掉(模式空间中只剩下内容2)然后启动另外一个循环。
  5. 在下一个循环中,N命令将附加一个换行符,并将下一个输入行添加到模式空间(例如“2’,’\ n’,’3“)。

下面列举了一些简单的例子,并配有相应的注释,可以结合结合起来理解
- $ 符号表示每个文件的最后一行
- ! 符号表示取反

讯享网 # 打印偶数行 sed -n 'n;p' FILE  # 将文件内容倒序输出 类似于 tac命令 sed '1!G;h;$!d' FILE  #打印出最后一行  sed 'N;D' FILE  # 打印最后两行 sed '$!N;$!D' FILE  # 除了最后一行,其余全删掉 也就是打印最后一行 sed '$!d' FILE  # 每行文字中间插入一个空白行 sed 'G' FILE  # 每一行文字都被空白行替换掉 sed 'g' FILE  # 删除多余的空白行,保证每行文字之间只有一个空白行 sed '/^$/d;G' FILE  # 输出奇数行 sed 'n;d' FILE  

通过上面的介绍,基本上说明了sed的用法。已经能够解决日常生产中90%的应用。由于文中例子以及介绍,均是笔者本人学习过程中的理解以及查阅资料所得,难免有失误之处,欢迎读者留言并指出错误所在,我会及时更正。

小讯
上一篇 2025-03-20 07:14
下一篇 2025-03-22 20:33

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/61299.html