Классика боли с sed — экранировать скобки, слеши и спецсимволы так, чтобы шелл их не съел раньше, чем сам sed их увидит: sed 's/\(foo\)\/\(bar\)/\2\/\1/' читается с третьего раза, а на реальном пути с точками и квадратными скобками превращается в ребус. sd написан на Rust и решает именно эту проблему — синтаксис замены простой и привычный, без тройного экранирования одного и того же символа.
Базовая замена — без слешей и без g в конце, подстановка глобальная по умолчанию:
echo 'hello before world before' | sd 'before' 'after'
# hello after world after
Для сравнения тот же результат через sed: sed 's/before/after/g' — короче, но стоит добавить в паттерн скобки или точку, и разница в читаемости становится заметна сразу.
Именованные группы захвата — ещё один момент, где sd выигрывает по читаемости: вместо позиционных \1, \2 можно писать осмысленные имена:
echo "123.45" | sd '(?P<dollars>\d+)\.(?P<cents>\d+)' '$dollars dollars and $cents cents'
# 123 dollars and 45 cents
Для литеральной замены без интерпретации regex есть флаг -F — полезно, когда в строке реально есть скобки и слеши, которые не нужно трактовать как спецсимволы:
echo 'lots((([]))) of special chars' | sd -F '((([])))' ''
# lots of special chars
Замена прямо в файле — так же, как у sed -i, только без разницы в поведении -i между GNU и BSD версией, которая обычно всплывает не вовремя:
sd 'window.fetch' 'fetch' http.js
sd не претендует на замену всех возможностей sed (стримовый построчный режим, скрипты на несколько команд) — это узкоспециализированный инструмент под самый частый сценарий: найти и заменить. Для этого сценария он быстрее с точки зрения набора команды руками, а не только по бенчмаркам.
#cli #rust
