# sed
# 定义
sed(Stream Editor)流编辑器,对标准输出或者文件逐行进行处理
# 语法格式
- pattern 是匹配的规则,可选,如果不选,则每一行都执行
# 第一种语法格式
stdout | sed [option] “pattern command”
# 第二种语法格式
sed [option] “pattern command” file
# 选项 option
sed 默认会打印源文件行,-n 可以只打印模式匹配行
如果有多个匹配条件的话,要加多个-e,只有单个匹配条件的话,-e 是默认的,不用添加
选项 | 含义 |
---|---|
-n | 只打印模式匹配行 |
-e | 直接在命令行进行 sed 编辑(单个条件默认添加) |
-f | 匹配命令保存在文件中,指定该文件执行 |
-r | 支持扩展的正则表达式 (Linux) |
-E | 支持扩展的正则表达式 (Maxos) |
-i | 直接修改文件内容 (Linux) |
-i ‘path’ | 直接修改文件内容 (强制填备份文件路径进行备份,不备份填''字符串)(Linux) |
sed.txt
i love cw
cw love me
we are family
we love each other
to the world end
sed.sh
这里的 p 相当于一个 command,是打印的意思
-n 就是一个 option
"/cw/p"中的/cw/就是 pattern,可以是字符串匹配,也可以是正则,都写在//(正则)中
⚠️ macOS 中-i 必须带-e 或者 跟一个"",表示空备份(macOS 中强行要求备份),也可以在""中写备份的文件名,做备份,否则会报 unterminated substitute pattern
sed "p" sed.txt
# i love cw
# i love cw
# cw love me
# cw love me
# ww are family
# ww are family
sed -n "p" sed.txt
# i love cw
# cw love me
# ww are family
sed -n "/cw/p" sed.txt
# cw love me
# ww are family
# 多个匹配条件
sed -n -e "/cw/p" -e "/we/p" sed.txt
# i love cw
# cw love me
# we are family
# we love each other
# 等价于
sed -nE "/cw|we/p" sed.txt
# 直接替换文本内容
sed -n -i -e "s/like/love/g;p" sed.txt
# 或者
sed -n -i "" "s/like/love/g;p" sed.txt
# pattern 详解
- 这里的 command 是指满足 sed 的操作命令,比如 p 代表打印
# pattern 用法表
匹配模式 | 含义 |
---|---|
10command | 匹配到第 10 行 |
10,20command | 匹配第 10-20 行 |
10,+5command | 匹配到 10-15 行 (maxos 中不能这么用) |
/pattern1/command | 匹配到 pattern1 的行 (用得最多) |
/pattern1/,/pattern2/command | 从匹配到 pattern1 的行 开始,知道匹配到 pattern2 的行结束(用得最多) |
10,/pattern1/command | 从第 10 行开始匹配,直到匹配到 pattern1 的行结束 |
/pattern1/,10command | 从匹配到 pattern1 的行开始,直到第 10 行结束 |
# 打印文件的第3行
sed -n "3p" sed.txt
# 打印文件的第2-4行
sed -n "2,4p" sed.txt
# 打印文件以we开头的行
sed -n "/^we/p" sed.txt
# 匹配从i开头的行到we开头的行
sed -n "/^i/,/^we/p" sed.txt
# i love cw
# cw love me
# we are family
# 编辑命令详解
macOS 上对 a 和 i 有很多坑,具体可以参照macOS 上 i 和 a 的坑
macOS 上 s/old/new/ig 中没有 i 这个选项
多个命令中间用 ; 隔开
⚠️ 在使用正则的时候有很多坑,不一定所有的正则都适用
macOS 中
s/old/new/
与其他非s/old/new/
内置支持的编辑命令连用需要用;分开并写在最后,以把s/old/new/
当作一个单独的编辑命令,如下
sed -i "" "s/love/like/;=" sed.txt
其他的编辑命令则不需要
sed -n "/love/=" sed.txt
- 使用变量替换的时候,替换规则必须用双引号,或者使用单引号将变量扩起来
old_str=love
new_str=LOVE
sed -i '' "s/$old_str/$new_str/g" sed.txt
# 等价
sed -i '' 's/'$old_str'/'$new_str'/g' sed.txt
# 编辑命令对照表(主要)
^一般表示开头,$表示结尾,例如$d 则表示删除到最后一行
/^$/command 表示操作空行 ^表示从开头$表示直接到结尾,中间没有任何字符则表示空行
/[:blank:]*/command 表示对多个空格进行 command
类别 | 编辑命令 | 含义 |
---|---|---|
查询 | p | 打印 |
增加 | a content | 行后追加 content |
增加 | i content | 行前追加 content |
增加 | r | 外部文件读入,行后追加 |
增加 | w | 匹配行写入外部文件 |
删除 | d | 删除 |
修改 | s/old/new | 将行内第一个 old 替换为 new |
修改 | ns/old/new | 将第 n 行内第一个 old 替换为 new |
修改 | s/old/new/g | 将行内全部 old 替换为 new |
修改 | s/old/new/m | 将每一行内第 m 个 old 替换为 new |
修改 | ns/old/new/m | 将第 n 行内第 m 个 old 替换为 new |
修改 | s/old/new/ng | 将行内第 n 个 old 开始全部替换为 new (Linux) |
修改 | s/old/new/ig | 将行内全部 old 替换为 new,忽略大小写 (Linux) |
修改 | /regular/s/old/new/g | 满足 regular(满足所有匹配模式)的行中所有 old 替换成 new |
# 编辑命令对照表(其他)
类别 | 编辑命令 | 含义 |
---|---|---|
其他 | # | 显示匹配内容的行号(Linux) |
其他 | # | 在每一行的前面插入一行作为该行的行号(macOS) |
- ⚠️ 一般情况下,编辑命令可以用单双引号,但是含有$等特殊字符表达特殊含义的时候必须使用单引号,例如
sed -i '' '1d' sed.txt # 正确
sed -i '' '/^we/,$d' sed.txt # 正确
sed -i '' "/^we/,$d" sed.txt # 错误,$d被当成变量了
# 删除第一行并打印(不修改源文件)
sed -n "1d;p" sed.txt
# 直接删除源文件第一行
sed -nie "1d" sed.txt
# 直接删除源文件第一至三行
sed -nie "1,3d;p" sed.txt
# 删除以c开头到we开头的行(不修改源文件)
sed -n "/^c/,/^we/d;p" sed.txt
# 删除以we开头的行致末尾
sed -i '' '/^we/,$d' sed.txt
# 删除#相关的注释和空行
sed -i '' '/[:blank:]*#/d;/^$/d' sed.txt
# 把sed-command.tx文件里面的内容放在sed.txt中以i开头的行后面
sed -i "" '/^i/r sed-command.txt' sed.txt
# 把符合条件的行保存在sed-save.txt中
sed -i "" '/^i/w sed-save.txt' sed.txt
# 将所有like替换成love
sed -n -i "" "s/like/love/g;p" sed.txt
# 将第二行的love换成like
sed -i "" "2s/love/like/" sed.txt
# 将第一行的第二个love替换成like
sed -i "" "1s/love/like/2" sed.txt
# 将每一行的第二个love替换成like
sed -i "" "s/love/like/2" sed.txt
# 将以we开头的行中所有love替换成love much
sed -i '' '/^we/s/love/love much/g' sed.txt
# 将满足cw的行到we的行之间的所有行中love换成ai
sed -i '' '/cw/,/we/s/love/ai/g' sed.txt
# 输出匹配love行的行号
sed -n "/love/=" sed.txt
# 反向引用
语法 1:使用&代表匹配内容
语法 2:使用\1 代表匹配内容,前提是匹配规则中需要用()扩起来代表\1 的内容(括号要转义)
语法 2 更灵活,可以匹配任意位置和数量的,使用()扩起来,多个使用\1、\2...即可
sed.txt
i lo11ves cw LOVE
cw lo22ves me
we are family
we lo33ves each other lo44ves
to the world end
# 将所有行匹配lo..ve的替换成lo..ves
sed -i "" "s/lo..ve/&s/g" sed.txt
# 等价于
sed -i "" "s/\(lo..ve\)/\1s/g" sed.txt
# 灵活匹配替换位置,替换lo\(..\)ve为lo..o
sed -i "" "s/lo\(..\)ve/lo\1o/g" sed.txt
# 使用更多个括号匹配
sed -i "" "s/lo\(..\)v\(e\)/\1 and \2/g" sed.txt
i 11 and e cw LOVE
cw 22 and e me
we are family
we 33 and e each other 44 and e
to the world end
# 使用*作匹配的时候&只能取到*之前的内容
sed -i "" "s/lo*/&123/g" sed.txt
i lo12311ve cw LOVE
cw lo12322ve me
we are famil123y
we lo12333ve each other lo12344ve
to the worl123d end
- ⚠️mac 的坑
# Linux
sed -nie "/^we/a 123" sed.txt
# Mac这么写才相当于Linux的
sed -i '' "/^we/a\\
123
" sed.txt
# 这种写法会插在we行的开头
sed -i '' "/^we/i\\
123" sed.txt
# 这种写法会插在we行上一行
sed -i '' "/^we/i\\
123
" sed.txt
# 读取sed-command.txt的内容添加到以i开头的行后面
# maxos中如果sed-command.txt末尾没有空行,那么会贴合源文件内容
sed -i "" '/^i/r sed-command.txt' sed.txt
## sed-command.txt
#/cw/p
# 123
i love cw
/cw/p
123cw love me
we are family
we love each other
to the world end
# maxos中如果sed-command.txt末尾有空行,那么会贴合源文件内容(该表现与Linux一致)
sed -i "" '/^i/r sed-command.txt' sed.txt
i love cw
/cw/p
123
cw love me
we are family
we love each other
to the world end
# maxos千万不要这么写
sed -n -i "" "s/love/like/g" sed.txt # 这么写加上了 -n 会全部替换为空文本
# 正确写法-将文本中全部行的love替换成like
sed -i "" "s/love/like/g" sed.txt
# 忽略大小写只能通过正则扩展去,因为s/old/new/ig中没有i(Linux)这个选项
sed -Ei "" "s/love|LOVE/like/g" sed.txt
# `s/old/new/`与其他非`s/old/new/`内置支持的编辑命令连用需要用;分开并写在最后,以把`s/old/new/`当作一个单独的编辑命令
# 在每一行的前面插入一行作为该行的行号
sed -i "" "s/love/like/;=" sed.txt
← grep 和 egrep sed-练习 →