xixixi.lol
shell

我常用的几个 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 的话要写成 \(...\),很容易看错。

← 返回笔记