sd/README_zh-CN.md
2024-05-06 11:58:24 +08:00

5.6 KiB
Raw Blame History

sd - 搜索替换

sd 是一个直观的查找与替换命令行工具。

宣传

为什么要使用它而不是现有的任何工具?

无痛的正则表达式   sd 使用您已经熟悉的来自 JavaScript 和 Python 的正则表达式语法。不用再去处理 sedawk 的怪癖 - 立即提高生产力。

字符串文字模式   非正则表达式的查找和替换。不再需要反斜杠或记住哪些字符是特殊的并且需要转义。

易读易写   查找和替换表达式被拆分开来,这样更容易阅读和编写。不再需要处理未闭合和转义的斜杠。

智能、常识性的默认设置   默认设置遵循常识,专为典型的日常使用而定制。

与 sed 相比

虽然 sed 可以做更多的事情,但 sd 专注于做一件事情,并且做得很好。以下是一些精选的例子,展示了 sd 的优势所在。

替换所有出现的内容的更简单语法:

  • sd: sd before after
  • sed: sed s/before/after/g

将换行符替换为逗号:

  • sd: sd '\n' ','
  • sed: sed ':a;N;$!ba;s/\n/,/g'

从包含斜杠的字符串中提取内容:

  • sd: echo "sample with /path/" | sd '.*(/.*/)' '$1'

  • sed: echo "sample with /path/" | sed -E 's/.*(\\/.*\\/)/\1/g'

    使用 sed你可以使用不同的分隔符来改善但仍然有些混乱

    echo "sample with /path/" | sed -E 's|.*(/.*/)|\1|g'

原地修改文件:

  • sd: sd before after file.txt

  • sed: sed -i -e 's/before/after/g' file.txt

    在使用 sed 时,需要记住使用 -e,否则某些平台会将下一个参数视为备份后缀。

基准测试

在大约 1.5GB 大小的 JSON 文件上进行简单的替换

hyperfine --warmup 3 --export-markdown out.md \
  'sed -E "s/\"/'"'"'/g" *.json > /dev/null' \
  'sed    "s/\"/'"'"'/g" *.json > /dev/null' \
  'sd     "\"" "'"'"'"   *.json > /dev/null'
命令 平均 [s] 最低…最高 [s]
sed -E "s/\"/'/g" *.json > /dev/null 2.338 ± 0.008 2.332…2.358
sed "s/\"/'/g" *.json > /dev/null 2.365 ± 0.009 2.351…2.378
sd "\"" "'" *.json > /dev/null 0.997 ± 0.006 0.987…1.007

结果:速度提高了大约 2.35 倍

对一个约 55M 大小的 JSON 文件进行正则表达式替换:

hyperfine --warmup 3 --export-markdown out.md \
  'sed -E "s:(\w+):\1\1:g"    dump.json > /dev/null' \
  'sed    "s:\(\w\+\):\1\1:g" dump.json > /dev/null' \
  'sd     "(\w+)" "$1$1"      dump.json > /dev/null'
命令 平均 [s] 最低…最高 [s]
sed -E "s:(\w+):\1\1:g" dump.json > /dev/null 11.315 ± 0.215 11.102…11.725
sed "s:\(\w\+\):\1\1:g" dump.json > /dev/null 11.239 ± 0.208 11.057…11.762
sd "(\w+)" "$1$1" dump.json > /dev/null 0.942 ± 0.004 0.936…0.951

结果:速度提高了大约 11.93 倍

安装

通过 cargo 使用 cargo install sd 命令安装,或通过各种包管理器安装。

Packaging status

快速指南

  1. 字符串文字模式。默认情况下,表达式被视为正则表达式。使用 -F--fixed-strings 可以禁用正则表达式。

    > echo 'lots((([]))) of special chars' | sd -s '((([])))' ''
    lots of special chars
    
  2. 基本正则表达式的使用 - 让我们去掉一些末尾的空白符

    > echo 'lorem ipsum 23   ' | sd '\s+$' ''
    lorem ipsum 23
    
  3. 捕获组

    索引捕获组:

    > echo 'cargo +nightly watch' | sd '(\w+)\s+\+(\w+)\s+(\w+)' 'cmd: $1, channel: $2, subcmd: $3'
    cmd: cargo, channel: nightly, subcmd: watch
    

    命名捕获组:

    > echo "123.45" | sd '(?P<dollars>\d+)\.(?P<cents>\d+)' '$dollars dollars and $cents cents'
    123 dollars and 45 cents
    

    在不太可能出现歧义的情况下,通过使用 ${var} 而不是 $var 来解决。这里有一个例子:

    > echo '123.45' | sd '(?P<dollars>\d+)\.(?P<cents>\d+)' '$dollars_dollars and $cents_cents'
     and
    
    > echo '123.45' | sd '(?P<dollars>\d+)\.(?P<cents>\d+)' '${dollars}_dollars and ${cents}_cents'
    123_dollars and 45_cents
    
  4. 在文件中查找并替换

    > sd 'window.fetch' 'fetch' http.js
    

    就是这样,文件将直接在原地修改。

    预览更改:

    > sd -p 'window.fetch' 'fetch' http.js
    
  5. 在整个项目中查找并替换

    这个例子使用了 fd

    好的 Unix 哲学来拯救我们了。

    fd --type file --exec sd 'from "react"' 'from "preact"'
    

    同理,但带有备份(考虑版本控制)。

    fd --type file --exec cp {} {}.bk \; --exec sd 'from "react"' 'from "preact"'
    

极端情况

sd 会将以 - 开头的每个参数解释为(可能是未知的)标志。 尊重常见的惯例,使用 -- 来表示标志的结束:

$ echo "./hello foo" | sd "foo" "-w"
error: Found argument '-w' which wasn't expected, or isn't valid in this context

USAGE:
    sd [OPTIONS] <find> <replace-with> [files]...

For more information try --help
$ echo "./hello foo" | sd "foo" -- "-w"
./hello -w
$ echo "./hello --foo" | sd -- "--foo" "-w"
./hello -w

转义特殊字符

要转义 $ 字符,需使用 $$

 echo "foo" | sd 'foo' '$$bar'
$bar