我常用的几个 sed 片段
sed 的语法第一次看很反人类,用熟了之后又觉得别的文本工具都不如它顺手。 这篇记的都是我实际会敲的命令,不带解释性的边角特性。
替换,但只在第 n 次出现的地方
g 是整行全部替换。不带 g 只换第一次。
换第 n 次就写数字:
# 只换每行第 2 个 foo
sed 's/foo/bar/2' file.txt
# 从第 3 个开始全换
sed 's/foo/bar/3g' file.txt
第二种我用了很多次才发现,之前一直是拿 awk 凑的。
就地修改,留备份
sed -i.bak 's/old/new/g' file.conf
-i 后面跟的字符串会作为后缀生成备份文件。
只想先看看改完长什么样,别加 -i,输出到终端。
路径里的斜杠太多
替换的定界符不一定是 /,换别的字符可以避免满地转义:
sed -i 's#/usr/local/lib#/opt/lib#g' config
|、#、, 都行,挑一个原文里没出现过的。
删掉行尾空白
提交前顺手清一下,避免 diff 里一片红:
sed -i 's/[[:space:]]*$//' *.go
注意这会把行尾的 tab 也删掉。有些格式对缩进敏感的文件别这么干。
提取两个标记之间的内容
sed -n '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/p' bundle.pem
-n 关掉默认输出,p 显式打印命中的行。
区间是从第一个匹配开始,到下一个结束标记为止,然后重复。
一个文件里有多段的话会全部提出去。
删空行和注释
sed -i '/^[[:space:]]*$/d' file
sed -i '/^[[:space:]]*#/d' file
改配置文件之前先备份,然后拿这个清一遍,剩下的就是真正生效的内容。
在匹配行后面追加
sed -i '/^\[core\]/a defaultBranch = main' .gitconfig
追加用 a,在前面插入用 i,都是整行操作。
macOS 自带的 sed 在这里语法不同,写脚本的时候要小心——
a\ 后面换行是 BSD 的写法。我一般是 gsed 或者干脆用 perl。
正则的分组引用
# 把 "123ms" 变成 "123 毫秒"
sed -E 's/([0-9]+)ms/\1 毫秒/g' log.txt
-E 是扩展正则,括号不用转义。\1 引用第一个分组。
不加 -E 的话要写成 \(...\),很容易看错。