sd
Intuitive find & replace CLI (sed alternative).
Official WebsiteFeatures
Intuitive SyntaxRegex SupportPreview ModeFast
Replaces
sedInstallation
Homebrew
brew install sdPacman (Arch)
pacman -S sdCargo (Rust)
cargo install sdWhy use sd?
sd eliminates the complex syntax of sed, providing an intuitive and easy-to-remember modern tool for string replacement.
Intuitive Syntax
No complex escaping like sed. Use slashes and other special characters directly.
Regex Support
Full support for powerful regex features like capture groups and lookahead/lookbehind.
Preview Mode
Preview changes before executing. Prevent unintended replacements and work safely.
Fast Processing
Built in Rust for high speed. Process large files and quantities without stress.
Basic Usage
Basic Syntax
Basic Commands
# Basic form: sd 'search pattern' 'replacement string' file
sd 'hello' 'world' file.txt
# Replace from standard input
echo 'hello world' | sd 'world' 'universe'
# Batch replace multiple files
sd 'old' 'new' *.txtSyntax Comparison with sed
Differences between sed and sd
# sed: requires delimiters and escaping
sed -i 's/hello/world/g' file.txt
sed -i 's/path\/to\/file/new\/path/g' file.txt
# sd: simple and intuitive
sd 'hello' 'world' file.txt
sd 'path/to/file' 'new/path' file.txt # No escaping slashes needed!Common Options
| Option | Description | Example |
|---|---|---|
-p | Preview mode (display changes only) | sd -p 'foo' 'bar' file.txt |
-s | Treat as literal string (disable regex) | sd -s '.*' 'literal' file.txt |
-f | Specify flags (i: case insensitive, m: multiline) | sd -f i 'hello' 'HELLO' file.txt |
-n | Replace only first N matches | sd -n 1 'foo' 'bar' file.txt |
Regex Patterns
Capture Groups
Using Capture Groups
# Capture with parentheses, reference with $1, $2
sd '(\w+)@(\w+)' '$2:$1' file.txt
# user@domain → domain:user
# Named capture groups
sd '(?P<name>\w+)@(?P<domain>\w+)' '$domain:$name' file.txt
# Convert date format
sd '(\d{4})-(\d{2})-(\d{2})' '$2/$3/$1' dates.txt
# 2024-01-15 → 01/15/2024Lookahead and Lookbehind
Lookahead/Lookbehind Patterns
# Positive lookahead: replace text before specific pattern
sd 'foo(?=bar)' 'baz' file.txt
# foobar → bazbar, foobaz → foobaz (no change)
# Positive lookbehind: replace text after specific pattern
sd '(?<=foo)bar' 'baz' file.txt
# foobar → foobaz
# Negative lookahead: replace only if not followed by specific pattern
sd 'foo(?!bar)' 'baz' file.txtCommon Regex Patterns
Practical Patterns
# Start and end of line
sd '^prefix' 'new_prefix' file.txt # Replace prefix at line start
sd 'suffix$' 'new_suffix' file.txt # Replace suffix at line end
# Whitespace handling
sd '\s+' ' ' file.txt # Multiple spaces to single space
sd '^\s+' '' file.txt # Remove leading whitespace
sd '\s+$' '' file.txt # Remove trailing whitespace
# Word boundaries
sd '\bword\b' 'replacement' file.txt # Replace whole word onlyPractical Examples
Direct File Editing
File Editing
# Edit single file directly
sd 'old_function' 'new_function' src/main.rs
# Batch edit multiple files
sd 'deprecated_api' 'new_api' src/*.js
# Recursive replacement with find
fd -e py | xargs sd 'print(' 'logger.info('
# Replace only files managed by git
git ls-files '*.ts' | xargs sd 'oldName' 'newName'Using with Pipes
Pipeline Integration
# Format JSON and replace values
cat config.json | sd '"debug": true' '"debug": false'
# Process log files
cat app.log | sd '\[(\d+)\]' 'PID:$1' | less
# Expand environment variables
cat template.env | sd '\$\{HOME\}' "$HOME"
# Change CSV column order
cat data.csv | sd '^([^,]+),([^,]+),(.+)$' '$2,$1,$3'Code Fixing Examples
Code Refactoring
# Rename function in bulk
sd 'getUserById' 'fetchUserById' src/**/*.ts
# Rewrite import statements
sd "from 'lodash'" "from 'lodash-es'" src/*.js
# Add variable type annotations
sd 'const (\w+) = ' 'const $1: string = ' file.ts
# Remove console.log
sd 'console\.log\([^)]*\);?\n?' '' src/*.js
# Update old React syntax to new format
sd 'React\.FC<(.+)>' 'FC<$1>' components/*.tsxComparison with sed
| Operation | sed | sd |
|---|---|---|
| Basic replacement | sed 's/foo/bar/g' | sd 'foo' 'bar' |
| Replacement with slashes | sed 's/a\\/b/c\\/d/g' | sd 'a/b' 'c/d' |
| Direct file editing | sed -i 's/foo/bar/g' file | sd 'foo' 'bar' file |
| Capture groups | sed 's/\\(.*\\)/[\\1]/g' | sd '(.*)' '[$1]' |
| Case insensitive | sed 's/foo/bar/gi' | sd -f i 'foo' 'bar' |
| Replacement with newlines | Complex command needed | sd 'foo\\nbar' 'baz' |
Detailed Comparison Examples
sed vs sd Detailed Comparison
# 1. URL path replacement
# sed (escaping nightmare)
sed 's/https:\/\/example\.com\/api\/v1/https:\/\/example\.com\/api\/v2/g' file
# sd (write as-is)
sd 'https://example.com/api/v1' 'https://example.com/api/v2' file
# 2. JSON value replacement
# sed
sed 's/"version": "[0-9]*\.[0-9]*\.[0-9]*"/"version": "2.0.0"/g' package.json
# sd
sd '"version": "[0-9]+\.[0-9]+\.[0-9]+"' '"version": "2.0.0"' package.json
# 3. Multi-line patterns
# sed (very complex)
sed -z 's/foo\nbar/baz/g' file
# sd (intuitive)
sd 'foo\nbar' 'baz' fileTips and Tricks
- •Always use preview mode (
-p) to confirm results before replacement. Especially important with regex - •Use
-soption to treat as literal string. Search for regex metacharacters like.*literally - •Combine with
fdorrgto efficiently process only files matching specific criteria - •Before doing large-scale replacements in Git repos, use
git stashor create a new branch to work safely - •Be careful with shell quoting. Use single quotes (') to prevent shell expansion
- •sd is written in Rust, so you can also install it easily with
cargo install sd