Automating Config Edits
A classic operations task is flipping a setting in a config file across many servers — enabling a feature flag, changing a port, or pointing a service at a new host. sed excels here because a single substitution can target a specific directive and apply identically everywhere, which is more reliable than manual editing. The key challenge is precision: your pattern must match the intended line and nothing else, so anchoring to the key name and, ideally, the start of the line prevents accidental edits to comments or similarly named settings.
Cricket analogy: It's like a captain setting an identical field for a specific batter across every match — one precise instruction (substitution) applied uniformly, rather than repositioning fielders by hand each time.
In-Place Editing with -i and Backups
The -i flag edits files in place rather than writing to stdout, which is what you want for config files. Crucially, you can supply a backup suffix: 'sed -i.bak s/old/new/ app.conf' rewrites the file and preserves the original as app.conf.bak. This gives you an instant rollback. There is a portability trap: GNU sed accepts 'sed -i' with no suffix (and 'sed -i.bak' attached), while BSD/macOS sed requires an explicit argument, so 'sed -i '' s/old/new/ file' with an empty string is needed there. Scripts that must run on both should always provide an explicit suffix or branch on the platform.
Cricket analogy: The .bak backup is like a DRS review saving the original decision — you make the change on the field, but the untouched footage is preserved so you can overturn it if it was wrong.
# Change a port, anchored to the key, keeping a backup (GNU sed)
sed -i.bak 's/^Port .*/Port 2222/' /etc/ssh/sshd_config
# Uncomment a directive: strip a leading '#' only for a specific key
sed -i 's/^#\s*\(PasswordAuthentication\)/\1/' /etc/ssh/sshd_config
# Portable in-place edit across GNU and BSD/macOS sed
if sed --version >/dev/null 2>&1; then
sed -i 's/^debug=.*/debug=false/' app.conf # GNU
else
sed -i '' 's/^debug=.*/debug=false/' app.conf # BSD/macOS
fi
# Idempotent: only change if value differs (grep guard before sed)
grep -q '^timeout=30$' app.conf || sed -i 's/^timeout=.*/timeout=30/' app.confsed -i is not atomic in the way you might hope on all systems, and an unanchored pattern is dangerous. 's/host/newhost/' without '^' or a key anchor can rewrite the word 'host' inside comments, unrelated values, or hostnames elsewhere in the file. Always anchor to the directive (e.g. '^Port ') and test with a dry run (no -i) first, inspecting the diff before committing the change to a production config.
Idempotency and Safety
In configuration management, edits should be idempotent — running the same command twice must leave the file in the same correct state. A substitution like 's/^timeout=.*/timeout=30/' is naturally idempotent because it always drives the value to 30. Trouble arises with append or insert operations (the a and i commands), which add a new line every run and can duplicate directives. Guarding with grep -q before appending, or using a substitution that targets the existing line, keeps repeated runs safe. This is exactly why tools like Ansible prefer dedicated modules, but sed remains invaluable for quick, well-guarded one-offs.
Cricket analogy: Idempotency is like a fielder who returns to the same fielding position no matter how many times play resets — running the setup twice leaves the field identical, not doubled up.
For robust config automation at scale, purpose-built tools (Ansible's lineinfile/blockinfile, Puppet, or augeas for structured formats) offer idempotency and structure-awareness sed lacks. Reach for sed for quick, guarded, one-off edits and reserve declarative config-management modules for fleets and reproducible infrastructure.
- Anchor patterns to the directive (e.g. '^Port ') so you edit exactly the intended line.
- -i edits in place; add a suffix like -i.bak to keep an instant-rollback backup.
- Portability trap: GNU 'sed -i' needs no suffix, but BSD/macOS requires 'sed -i ''.
- Prefer substitution (which converges to a value) over append/insert to stay idempotent.
- Guard append operations with 'grep -q' so repeated runs don't duplicate directives.
- Dry-run without -i and inspect the diff before touching a production config.
- For fleet-scale config management, dedicated tools (Ansible, augeas) beat raw sed.
Practice what you learned
1. What does the suffix in 'sed -i.bak s/old/new/ file' do?
2. Why is 's/host/newhost/' risky for editing a config file?
3. Which portability difference affects in-place editing?
4. Which edit is naturally idempotent?
Was this page helpful?
You May Also Like
Text Transformation Recipes
A practical cookbook of proven sed one-liners for everyday text surgery: deleting lines, extracting ranges, joining lines, and reformatting with capture groups.
sed in Shell Pipelines
How to wire sed into Unix pipelines as a stream filter, combining it with cat, grep, sort, and xargs to build powerful one-liner text-processing workflows.
Performance and Portability
How to write sed that runs fast on large files and behaves identically across GNU, BSD/macOS, and POSIX sed — covering common divergences and optimization techniques.
Related Reading
Related Study Notes in Programming
Browse all study notesApache Spark Study Notes
Programming · 30 topics
ProgrammingApache Flink Study Notes
Programming · 30 topics
ProgrammingHadoop Study Notes
Programming · 30 topics
ProgrammingSnowflake Study Notes
Programming · 30 topics
ProgrammingApache Airflow Study Notes
Programming · 30 topics
Programmingdbt (Data Build Tool) Study Notes
Programming · 30 topics