文件处理三剑客之sed

197 阅读2分钟

sed:stream editor 流编辑器。对标准输出或文件逐行进行处理。

Sed是从文件或管道中读取一行,处理一行,输出一行;再读取一行,再处理一行,再输出一行,直到 最后一行。每当处理一行时,把当前处理的行存储在临时缓冲区中,称为模式空间(Pattern Space),接着用sed命令处理缓冲区中的内容,处理完成后,把缓冲区的内容送往屏幕。接着处理下 一行,这样不断重复,直到文件末尾。一次处理一行的设计模式使得sed性能很高,sed在读取大文件时 不会出现卡顿的现象。如果使用vi命令打开几十M上百M的文件,明显会出现有卡顿的现象,这是因为 vi命令打开文件是一次性将文件加载到内存,然后再打开。Sed就避免了这种情况,一行一行的处理, 打开速度非常快,执行速度也很快

sed [OPTION]... 'script;script;...' [input-file]...

基本用法

OPTION:

  • -n 不输出模式空间内容到屏幕,即不自动打印,如果不加-n,会自动打印每一行
  • -e 当script有多个时,使用-e,多个script之间是或关系,-e 'script1' -e 'script2' 等同于 'script1;script2'
  • -f file 从指定文件中读取script
  • -r,-E 支持扩展正则表达式
  • -i 对文件直接进行修改,而不是输出到终端
  • -i.bak 先备份原文件再修改文件

script:

script是 地址 和 命令 的组合,地址用来定位,命令用来对定位的内容进行操作。

地址

  • 不给地址:对全文进行处理

  • 单地址:

    • #:#是阿拉伯数数字,指定行
    • $:最后一行
    • /pattern/:匹配到的每一行
  • 地址范围:

    • #,#:第#行到第#行 3,6 从第3行到第6行
    • #,+#:第#行开始,往后再匹配#行 3,+4 从第3行到第7行
    • /pattern1/,/pattern2/:从pattern1匹配到行,到pattern2匹配到的行,再往下继续,从pattern1匹配到行,到pattern2匹配到的行...
  • 步进:~

    • first~step:匹配first行,然后步进为step向后继续匹配,例如 1~2 就是匹配奇数行、2~2就是匹配偶数行。

命令

  • p:print 打印查询的行

  • Ip:忽略大小写输出

  • d:删除匹配到的行

  • a:append,追加内容到下一行 \n表示换行; 如果要解析空格,需要用反斜杠\

  • i text:insert,在行前面插入内容

  • c text:change,替换行

  • w file:保存模式匹配的行到指定文件

  • r file:从file中读取内容,插入到匹配到的行的下一行

  • =:打印匹配到行的行号

  • ! 命令:对没有匹配到的行进行处理,例如 !p 是打印未匹配到的行、!atext 是在未匹配到的行的下一行添加text

  • s/pattern/string/修饰符:查找替换 修饰符:

    • g:一行里如果由多个匹配到的内容,全部替换。默认只替换第一个。
    • p:打印替换成功的行
    • w file:将成功替换的行保存至文件中
    • I,i:忽略大小写

练习

1.将php.ini-production中的无关信息去掉

sed -E '/^; /d;/^;+;$/d' /usr/local/src/php-7.4.8/php.ini-production | uniq > php.ini 

2.获取分区利用率

lujinkai@Z510:~$ df | sed -En '/^\/dev\/sd/s/.* ([0-9]+)%.*/\1/p'

3.取基名和目录名

# 使用/作为分隔符,如果搜索条件中出现/需要转义,所以为了易读性,不建议使用搜索条件中出现的字符作为分割符
pwd |sed -r 's/(^\/.*\/)([^\/]+\/?)/\2/'	# 取基名
pwd |sed -r 's@(^/.*/)([^/]+/?)@\2@'	# 取目录

4.将非#开头的行加#

lujinkai@Z510:~/data/test$ sed -Ei 's/^[^#].*/# &/' a.log
# 或
lujinkai@Z510:~/data/test$ sed -Ei 's/(^[^#].*)/# \1/' a.log
# 或
lujinkai@Z510:~/data/test$ sed -ri '/^#/!s/^/# /' a.log	

5.将#开头的行删除#

lujinkai@Z510:~/data/test$ sed -ri 's/^#(.*)/\1/' a.log

高级用法

略。。。