🍺 BREW Explorer

← all formulae

sd

brew install sd v1.1.0 MIT

Intuitive find & replace CLI

1.2k
30-day installs · #1198
4.1k
90-day · #1193
11.5k
365-day · #1349
7.2k
★ GitHub stars · updated 5mo ago

Build dependencies

GitHub topics

cli command-line regex rust terminal text-processing

Links

Raw metadata
{
  "aliases": [],
  "alternatives": [],
  "build_dependencies": [
    "rust"
  ],
  "categories": [],
  "caveats": null,
  "conflicts_with": [],
  "dependencies": [],
  "deprecated": 0,
  "deprecation_reason": null,
  "desc": "Intuitive find \u0026 replace CLI",
  "disable_reason": null,
  "disabled": 0,
  "enrichment_fetched_at": "2026-06-20T23:41:22+00:00",
  "first_seen": "2026-06-20T23:34:18+00:00",
  "full_name": "sd",
  "github_default_branch": "master",
  "github_last_commit_at": "2026-02-25T19:26:21Z",
  "github_readme_excerpt": "# sd - `s`earch \u0026 `d`isplace\n\n`sd` is an intuitive find \u0026 replace CLI.\n\n## The Pitch\n\nWhy use it over any existing tools?\n\n*Painless regular expressions.* \u0026nbsp; `sd` uses regex syntax that you already know from JavaScript and Python. Forget about dealing with quirks of `sed` or `awk` - get productive immediately.\n\n*String-literal mode.* \u0026nbsp; Non-regex find \u0026 replace. No more backslashes or remembering which characters are special and need to be escaped.\n\n*Easy to read, easy to write.* \u0026nbsp; Find \u0026 replace expressions are split up, which makes them easy to read and write. No more messing with unclosed and escaped slashes.\n\n*Smart, common-sense defaults.* \u0026nbsp; Defaults follow common sense and are tailored for typical daily use.\n\n## Comparison to sed\n\nWhile sed does a whole lot more, sd focuses on doing just one thing and doing it well. Here are some cherry-picked examples where sd shines.\n\nSimpler syntax for replacing all occurrences:\n  - sd: `sd before after`\n  - sed: `sed s/before/after/g`\n\nReplace newlines with commas:\n  - sd: `sd -A \u0027\\n\u0027 \u0027,\u0027`\n  - sed: `sed \u0027:a;N;$!ba;s/\\n/,/g\u0027`\n\n  Note: this requires `-A` (across mode) since `\\n` is a cross-line pattern.\n\nExtracting stuff out of strings containing slashes:\n  - sd: `echo \"sample with /path/\" | sd \u0027.*(/.*/)\u0027 \u0027$1\u0027`\n  - sed: `echo \"sample with /path/\" | sed -E \u0027s/.*(\\\\/.*\\\\/)/\\1/g\u0027`\n    \n    With sed, you can make it better with a different delimiter,\n    but it is still messy:\n    \n    `echo \"sample with /path/\" | sed -E \u0027s|.*(/.*/)|\\1|g\u0027`\n\nIn place modification of files:\n  - sd: `sd before after file.txt`\n  - sed: `sed -i -e \u0027s/before/after/g\u0027 file.txt`\n    \n    With sed, you need to remember to use `-e` or else some\n    platforms will consider the next argument to be a backup suffix.\n\n## Benchmarks\n\n**Simple replacement on ~1.5 gigabytes of JSON**\n\n```sh\nhyperfine --warmup 3 --export-markdown out.md \\\n  \u0027sed -E \"s/\\\"/\u0027\"\u0027\"\u0027/g\" *.json \u003e /dev/null\u0027 \\\n  \u0027sed    \"s/\\\"/\u0027\"\u0027\"\u0027/g\" *.json \u003e /dev/null\u0027 \\\n  \u0027sd     \"\\\"\" ",
  "github_repo": "chmln/sd",
  "github_stars": 7205,
  "github_topics": [
    "cli",
    "command-line",
    "regex",
    "rust",
    "terminal",
    "text-processing"
  ],
  "homepage": "https://github.com/chmln/sd",
  "homepage_og_description": null,
  "homepage_og_image": null,
  "homepage_title": null,
  "installs_30d": 1221,
  "installs_365d": 11503,
  "installs_90d": 4145,
  "keg_only": 0,
  "keg_only_reason": null,
  "last_seen": "2026-06-20T23:34:18+00:00",
  "license": "MIT",
  "llm_generated_at": null,
  "llm_model": null,
  "name": "sd",
  "oldnames": [],
  "one_liner": null,
  "optional_dependencies": [],
  "rank_30d": 1198,
  "rank_365d": 1349,
  "rank_90d": 1193,
  "raw_hash": "79079c9fa6fa2528",
  "recommended_dependencies": [],
  "revision": 0,
  "ruby_source_path": "Formula/s/sd.rb",
  "tap": "homebrew/core",
  "test_dependencies": [],
  "uses_from_macos": [],
  "version_head": null,
  "version_stable": "1.1.0",
  "versioned_formulae": [],
  "why_use_this": null
}