Linux sed流编辑器

sed流编辑器

sed是一种流编辑器,流编辑器会在编辑器处理数据之前基于预先提供的一组规则来编辑数据流。
sed编辑器可以根据命令来处理数据流中的数据,这些命令要么从命令行中输入,要么存储在一个命令文本文件中。

sed 的工作流程主要包括读取、执行和显示三个过程

•读取:sed 从输入流(文件、管道、标准输入)中读取一行内容并存储到临时的缓冲区中(又称模式空间,pattern space)。
•执行:默认情况下,所有的sed 命令都在模式空间中顺序地执行,除非指定了行的地址,否则sed 命令 将会在所有的行上依次执行。
•显示:发送修改后的内容到输出流。在发送数据后,模式空间将会被清空。在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

在所有的文件内容都被处理完成之前,上述过程将重复执行,直至所有内容被处理完。

注意默认情况下所有的sed命令都是在模式空间内执行的,因此输入的文件并不会发生任何变化,除非是用重定向存储输出。

sed 处理大文件很卡怎么办(重中之重)

  1. 用cat 输出 | 交给sed (这时就不通过IO一行行读文件,而是cat一次性读取完成 再缓存中直接取)
    cat 文件 | grep / sed / awk
  2. split切块文件 for循环依次读取执行

目录

sed流编辑器

sed 处理大文件很卡怎么办

sed命令示例

 打印内容

 输出行号

打印不可见字符 

 同时使用多个操作符

使用地址

打印指定行

 退出sed

 显示奇数行

使用文本输出匹配的行

多条件根据文本筛选

行号 字符串 配合使用

删除行

指定行号

正则表达式 

删除空行的三种方法

行号 字符串 配合使用

替换 

正则表达式 替换

 sed文件中读取命令执行

 保存修改结果

避免路径 / 被误判为分隔符 /         使用  \   或是  直接修改分隔符

插入

替换行

转换字符

行前行后 插入行

读取其他文件内容插入当前文件

保持空间 实现复制剪切

剪切效果

复制效果

分片重组



sed命令格式

sed -e 'n{
操作1
操作2
...
}' 文件1 文件2 ...

常用选项

-e 或--expression=:表示用指定命令来处理输入的文本文件,只有一个操作命令时可省略,一般在执行多个操作命令使用
-f 或--file=:表示用指定的脚本文件来处理输入的文本文件。
-h 或--help:显示帮助。
-n、--quiet 或 silent:禁止sed编辑器输出,但可以与p命令一起使用完成输出。
-i:直接修改目标文本文件。
sed -e '操作' 文件1 文件2 ...  
-e 指定操作字符

sed -n -e '操作' 文件1 文件2 ...
-n 不显示

sed -f 脚本文件 文件1 文件2 ...
-f 调用文本文件中的命令

sed -i -e '操作' 文件1 文件2 ...
-i 会修改文件内容

常用操作

s:替换,替换指定字符。
d:删除,删除选定的行。
a:增加,在当前行下面增加一行指定内容。
i:插入,在选定行上面插入一行指定内容。
c:替换,将选定行替换为指定内容。
y:字符转换,转换前后的字符长度必须相同,对应替换,类似tr命令替换用法。
p:打印,如果同时指定行,表示打印指定行;如果不指定行,则表示打印所有内容;如果有非打印字符,则以 ASCII 码输出。其通常与“-n”选项一起使用,避免输出两次。
n:移动到下一行
=:打印行号。
l(小写L):打印数据流中的文本和不可打印的ASCII字符(比如结束符$、制表符\t)
q:跟上数字(例如5q) 指定第几行输出后退出流编辑器


sed命令示例

 打印内容

sed -n -e 'p' testfile1 #-n不显示结果 -e指定操作字符 'p'显示结果
cat festfile | sed -n -e 'p' #先cat输出再sed 同义
cat festfile | sed -n 'p' #只有一个操作符的情况可以省略-e

 输出行号

sed -n -e '=' testfile1   # '='输出行号
cat festfile | sed -n '=' | tail -l #输出最后一行行号(统计行数)
cat festfile | wc -l #更简单的统计行数

打印不可见字符 

sed -n -e 'l' testfile1 #'l'打印不可见字符

 同时使用多个操作符

sed -n -e '=;p' testfile1  #同时打印行号和内容的3种写法 ; 分隔操作符

sed -n -e '=' -e 'p' testfile1 #同时打印行号和内容的3种写法 每个操作符一个-e

sed -n '  #同时打印行号和内容的3种写法 回车分批输入
> =
> p
> ' testfile1

sed -n '=  
> p
> ' testfile1


使用地址

sed编辑器有2种寻址方式:
1、以数字形式表示行区间
2、用文本模式来过滤出行

打印指定行

sed -n '4p' testfile1 #打印第四行
sed -n '$p' testfile1 #打印末尾行
sed -n '1,3p' testfile1 #打印1-3行      !需要加-n屏蔽原来的输出不然默认从第一行输出到最后一行!
sed -n '3,$p' testfile1 #打印3行到最后行
sed -n '3p;$p' testfile1 #打印3行和最后行
sed -n '1,+3p' testfile1    #打印1之后的连续3行,即1-4行

 退出sed

sed '5q' testfile1            #打印前5行信息后退出,q表示退出

 显示奇数行

sed -n 'p;n' testfile1        #打印奇数行 
第一行p显示行。第二行n跳过一行到第三行。第三行显示,第四行不显示...

sed -n 'n;p' testfile1        #打印偶数行

sed -n '2,${n;p}' testfile1   #第二行开始,执行n;p,输出一行跳过一行(3 5 7 9 11...)

sed -n '3 {p;n;n;p}' testfile1   #✨在第三行执行 输出 换行两次 输出(3 5)
sed -n '3,${p;n;n;p}' testfile1  #✨在第三行到最后一行执行 输出 换行两次 输出(3 5 6 8 9...)

传统的for循环写法
a=0
for i in $(cat ./testfile1)
do
    let a++
    if [ $[a%2] -eq 1 ];then
        echo "$i 奇数行"
    else
        echo "$i 偶数行"
    fi
done

使用文本输出匹配的行

sed -n '/root/p' /etc/passwd  #显示包含root的行    /文字/p(显示)

sed -n '/^root/p' /etc/passwd #添加正则表达式 root开始的行
sed -n '/bash$/p' /etc/passwd #添加正则表达式 bash结尾的行

多条件根据文本筛选

sed -n -e '/ftp/p' -e '/root/p' /etc/passwd #筛选既有root又有ftp的行

sed -nr '/ftp|root/p' /etc/passwd  #合并写法 加上-r 使用扩展正则表达式

sed -n '/ftp\|root/p' /etc/passwd  #合并写法 加上 \

行号 字符串 配合使用

sed -n '2,/nobody/p' /etc/passwd #从第二行开始,到第一个包含nobody的行结束

sed -n '2,/nobody/=' /etc/passwd #显示‘从第二行开始,到第一个包含nobody的行结束’的行号

sed -nr '/ro?t/p' /etc/passwd #-r表示支持扩展正则表达式 ?匹配一次前面的内容(o)
sed -nr '/ro+t/p' /etc/passwd #-r表示支持扩展正则表达式 +匹配一次或多次前面的内容(o)
sed -nr '/ro*t/p' /etc/passwd #-r表示支持扩展正则表达式 +匹配0次或多次前面的内容(o)
sed -nr '/ro{1,}t/p' /etc/passwd #-r表示支持扩展正则表达式 {1,}匹配一次或多次前面的内容(o)
sed -n '/ro\{1,\}t/p' /etc/passwd #若不加-r代表扩展正则表达式 需要加上 \ 

删除行

指定行号

sed 'd' testfile1       #全删(因为流编辑器一行行执行,代表每行都执行删除)
sed '3d' testfile1      #删除3行
sed '2,4d' testfile1    #删除2-4行

正则表达式 

sed '$d' testfile1      #删除最后一行
sed '/^$/d' testfile1   #删除空行 ^$(开头结尾 表示空行)

sed '/nologin$/d' /etc/passwd  #删除nologin结尾行
sed '/nologin$/!d' /etc/passwd #“!”表示取反操作

删除空行的三种方法

grep -v "^$"
tr -s '\n'
sed '/^$/ d'

行号 字符串 配合使用

sed '2,/3/d' testfile2 #从第二行开始删到第一个包含3的行

sed '/1/,/3/d' testfile2  #从第一个包含2的行开启删除功能 删到第一个包含3的行 关闭删除功能

注意,使用字符串匹配删除,会寻找第一个包含字符串(1)位置的行 开启删除功能 删除到第二个包含字符串(3)位置的行 关闭删除功能
若接下来的匹配中又遇到了包含第一个字符串(1)位置的行,还会
继续开启删除功能,直到遇到第二个包含字符串(3)位置的行 关闭删除功能。(若没有则一删到底)

根据字符串匹配删除不够准确 容易误删 最好还是指定行号进行删除

替换 

行范围 s/旧字符串/新字符串/替换标记

                        4种替换标记
数字:替换行内第x个被匹配到的字符串
g:替换所有匹配的字符串
p:打印被替换的行,与-n一起使用
w 文件:将替换的结果写到文件中
sed -n 's/root/admin/p' /etc/passwd #将行内第一个root替换成admin p输出替换的行 -n不显示所有行

sed -n 's/root/admin/2p' /etc/passwd #将行内第二个匹配到的root替换成admin

sed -n 's/root/admin/gp' /etc/passwd #行内所有root替换成admin

sed -n 's/root//gp' /etc/passwd #删除行内所有root(替换为空)

正则表达式 替换

sed -n 's/^#//p' /etc/passwd #去除注释,开头#替换为空 -n不输出文件 p输出更改结果
sed '1,20 s/^/#/' /etc/passwd #1-20行 行首[空]替换为[#] (添加注释#)

sed '/^root/ s/$/#/' /etc/passwd #root开头行 末尾加上#
sed '/root/ s/^/#/' /etc/passwd  #包含root行 末尾加上#

sed '/swap/ s/^/#/' /etc/fatab #注释掉etc/fatab中自动挂载的swap分区 开头加上#

sed -rn 's/.*root.*/#&/p' /etc/passwd  #直接写正则用s替换,不用传统写法,比较麻烦这种写法
# /.*root.*/  包含root的行  (.*   .代表匹配任意一个字符 *代表匹配前面的表达式0次或多次)  
#   #&中 &表示前面正则表达式匹配到的内容 #在匹配到内容前加上#号

 sed文件中读取命令执行

sed -f script.sed /etc/passwd #从script.sed文件中读取sed命令执行

script.sed文件内容
/^root/ s/^/#/ #注释 root开头行 开头加上#
s/ftp/mysed/g  #ftp 全部 替换为mysed
/nologin$/ d   #删除nologin结尾行

 保存修改结果

方法1 重定向输出 (保存所有)
sed '1,20 s/^/#/' /etc/passwd > new.txt #1-20行 添加注释# 并且重定向输出
方法1 重定向输出 (只保存修改的行内容)
sed -n '1,20 s/^/#/p' /etc/passwd > new.txt #-n不输出全部 p输出修改内容

方法2 w命令(只保存修改的行内容)
sed '1,20 s/^/#/w new.txt' /etc/passwd  #1-20行 添加注释# 并且保存
sed '1,20w out.txt' /etc/passwd #1-20行保存

避免路径 / 被误判为分隔符 /         使用  \   或是  直接修改分隔符

sed -n 's/\/bin\/bash/\/sbin\/nologin/p' /etc/passwd 
#/bin/bash改为/sbin/nologin 需要加\避免系统误判/路径为/分隔符
#'s/   \/bin\/bash   /   \/sbin\/nologin   /p'

上面的写法可读性差,可以直接替换分隔符 
只需要任意字符紧跟替换符号 s 后,就会将这个字符识别为分隔符
sed -n 's!/bin/bash!/sbin/nologin!p' /etc/passwd  #使用“!”作为字符串分隔符
sed -i 's9\945\9\99\98\939g' test.txt #将94599替换为9893 并i写入文件 \9代表普通字符 9代表分隔符
# 's9   \945\9\9   9   \98\93   9g' [ \9为用 \ 取消9的分隔符含义,表示普通9字符 ]


插入

替换行

sed '1c hello world' testfile1  #第一行整行替换为 hello world
sed '10c hello world' testfile1 #第十行整行替换为 hello world
sed '$c hello world' testfile1  #最后行整行替换为 hello world

sed '/45/c ABC' testfile2 #包含45的行替换为ABC

转换字符

sed 'y/our/ABC/' testfile2   #使所有的o字符转换成A,所有的u字符转换成B,所有的r字符转换成C

行前行后 插入行

行前插入
    #根据行号
sed '1a 123' testfile1 #在第一行后插入123行(第二行:123)
sed '$a 123' testfile1 #在最后一行后插入123行(追加效果)
sed '1,3a 123' testfile1 #1-3行后都插入123
    #根据字符串匹配
sed '/^t/a 123' testfile1 #匹配t开头的行 在行后插入123

行后插入
    #根据行号
sed '1i 123' testfile2 #在第一行前插入123行(第一行:123)
sed '$i 123' testfile2 #在最后一行前插入123行
sed '1,3i 123' testfile2 #1-3行前都插入123
    #根据字符串匹配
sed '/^t/i 123' testfile1 #匹配t开头的行 在行前插入123

读取其他文件内容插入当前文件

sed '5r /etc/resolv.conf' testfile2 #在第5行后追加插入/etc/resolv.conf文件内容
sed '$r /etc/resolv.conf' testfile2 #在最后行后追加插入/etc/resolv.conf文件内容

保持空间 实现复制剪切

        

        sed除了缓冲空间用于逐行处理,还有一个保持空间,可以用于保持存储信息。

剪切效果

sed '/root/{H;d};$G' /etc/passwd    
#将包含root的行剪切到末尾 H复制到剪切板d删除(结合实现剪切) 
#G表示粘贴到指定行后 $G粘贴到最后一行

sed '1,3{H;d};$G' /etc/passwd            
#将1、2行剪切 粘贴到最后一行下面
粘贴到最后一行后可能遇到文件末尾换行符,加上sed '/^$/d' 删除空行
sed '1,3{H;d};$G' /etc/passwd | sed '/^$/d'

sed '1,3{H;d};10,$G' /etc/passwd  #剪切1-3行 10-最后行每行粘贴

        在vi编辑器中在:命令模式中输入✨   1,3 m 10      把1-3行剪切到10行后

复制效果

sed '1,2H;3,4G' /etc/passwd            
#将1、2行复制 粘贴到3和4行的下面(3 4行每行后都会加上1 2行内容)

sed '1,3H;$G' /etc/passwd            
#将1、2行复制 粘贴到最后一行下面
复制到最后一行后可能遇到文件末尾换行符,加上sed '/^$/d' 删除空行
sed '1,3H;$G' /etc/passwd | sed '/^$/d'

sed '1,3H;10,$G' /etc/passwd  #复制1-3行 10-最后行每行粘贴

         在vi编辑器中在:命令模式中输入✨   1,3 co 10     把1-3行复制到10行后

分片重组

先( )指定分片 再\指定每个分片位置重组

echo "111222333" | sed -r 's/(111)(222)/\2\1/'    #-r使用扩展正则表达式
#将字符 111 和 222 互换位置

echo "111222333" | sed -r 's/(111)(222)(333)/\3\2\1/'    #-r使用扩展正则表达式
#将字符 111 和 222 互换位置

首尾字符交换
echo "111222333" | sed -r 's/^(.)(.*)(.)$/\3\2\1/'        
#第一个字符 最后一个字符 交换
# 's/^(.)(.*)(.)$    ^(.)第一个任意字符 (.*)任意字符任意次 (.)$最后一个任意字符
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值