Shell Scripting SED Script Files Advanced May 2026

Shell Scripting Advanced SED: Scripts & Files

Store SED programs in reusable script files, compose multiple scripts with -f, process multiple input files consistently, use sed for in-place batch editing across directories, and combine sed with find for fleet-wide config updates.

Once a SED transformation grows beyond a one-liner, it belongs in a script file. The -f flag loads SED commands from a file, enabling version control, reuse, and comments. Combined with find and xargs, a SED script file becomes a fleet-wide config transformation tool.

SED
#!/usr/bin/env sed -f
# normalise_config.sed — Clean and normalise config files
# Usage: sed -f normalise_config.sed input.conf
#        sed -f normalise_config.sed -i input.conf  (in-place)
#
# Comments in .sed files use #
# Each line is a sed command; semicolons separate inline commands

# ── Remove comment lines and blank lines ──────────────────
/^[[:space:]]*#/d
/^[[:space:]]*$/d

# ── Trim whitespace ───────────────────────────────────────
s/^[[:space:]]*//
s/[[:space:]]*$//

# ── Normalise = spacing (key=val, key = val → key=val) ────
s/[[:space:]]*=[[:space:]]*/=/

# ── Uppercase section headers ─────────────────────────────
/^\[/{
  y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
}

# ── Substitute known legacy key names ─────────────────────
s/^DB_SERVER=/DB_HOST=/
s/^DATABASE_NAME=/DB_NAME=/
s/^MYSQL_PASSWORD=/DB_PASS=/
BASH
# ── Apply multiple .sed files in sequence ─────────────────
sed -f strip_comments.sed -f normalise_keys.sed -f update_values.sed config.env

# ── Mix -f files with -e inline commands ─────────────────
sed -f base_transforms.sed -e "s/old_host/${NEW_HOST}/g" template.conf

# ── sed script files directory — managed library ──────────
ls /etc/myapp/sed-rules/
# 01_strip_legacy.sed
# 02_normalise_keys.sed
# 03_set_defaults.sed
# 04_validate_values.sed

apply_transforms() {
  local file="${1}"
  local args=()
  for script in /etc/myapp/sed-rules/*.sed; do
    args+=(-f "${script}")
  done
  sed "${args[@]}" "${file}"
}

apply_transforms /etc/myapp/config.env > /tmp/config.env.new
diff /etc/myapp/config.env /tmp/config.env.new
mv /tmp/config.env.new /etc/myapp/config.env
BASH
# ── Update all config files in a directory ────────────────
find /etc/myapp -name "*.conf" -type f \
  -exec sed -i 's/old-host/new-host/g' {} +

# ── Update all files but only if the pattern exists (faster)
grep -rl "old-host" /etc/myapp/ | \
  xargs sed -i 's/old-host/new-host/g'

# ── Batch update with backup ──────────────────────────────
find /etc -name "*.conf" -exec sed -i.bak '
  s/DB_HOST=.*/DB_HOST=prod-db-01/
  s/DB_PORT=.*/DB_PORT=5432/
' {} +

# ── Version bump across all script files ─────────────────
find /opt/myapp/bin -type f -name "*.sh" | \
  xargs grep -l "VERSION=" | \
  xargs sed -i -E \
    's/(^readonly VERSION=")[0-9]+\.[0-9]+\.[0-9]+(")/\12.2.0\2/'

# ── Apply sed script file across entire codebase ──────────
find /opt/myapp -type f \( -name "*.conf" -o -name "*.env" \) \
  -exec sed -i -f /opt/myapp/scripts/migrations/v2.sed {} +

# ── Dry run first — pipe through sed without -i ───────────
find /etc/nginx -name "*.conf" | while read -r f; do
  diff "${f}" <(sed 's/old/new/g' "${f}") && echo "  No changes: ${f}"
done
BASH
#!/usr/bin/env bash
# deploy_config.sh — Generate per-environment configs from template

set -euo pipefail

TEMPLATE="/opt/myapp/config/app.conf.template"
ENV="${1:?Usage: deploy_config.sh ENV}"

# Load env-specific values
source "/opt/myapp/config/${ENV}.env"

# Generate config via sed substitution
sed "
  s|{{DB_HOST}}|${DB_HOST}|g
  s|{{DB_PORT}}|${DB_PORT:-3306}|g
  s|{{DB_NAME}}|${DB_NAME}|g
  s|{{APP_ENV}}|${ENV}|g
  s|{{LOG_LEVEL}}|${LOG_LEVEL:-INFO}|g
  s|{{CACHE_TTL}}|${CACHE_TTL:-300}|g
  /{{[A-Z_]*}}/d    # delete any unfilled placeholders
" "${TEMPLATE}" > "/etc/myapp/${ENV}.conf"

# Verify no placeholders remain
if grep -q '{{.*}}' "/etc/myapp/${ENV}.conf"; then
  echo "ERROR: Unfilled placeholders remain" >&2
  exit 1
fi

echo "  ✔ Config generated for ${ENV}: /etc/myapp/${ENV}.conf"
sed — batch config update
vriddh@prod-01:~/scripts$grep -rl "old-db-01" /etc/myapp/ | xargs sed -i 's/old-db-01/prod-db-01/g'
✔ Updated 4 files
vriddh@prod-01:~/scripts$./deploy_config.sh production
✔ Config generated for production: /etc/myapp/production.conf
vriddh@prod-01:~/scripts sed -f normalise_config.sed -i /etc/myapp/*.conf && echo "All normalised"
All normalised
✔ SED scripts and files — Store multi-command SED programs in .sed files run with sed -f script.sed. Compose pipelines with multiple -f files. Use grep -rl pattern | xargs sed -i — far faster than running sed on every file when only a few need changes. Always dry-run with diff file <(sed 's/old/new/' file) before using -i on production configs. Use double-quoted sed scripts when you need shell variable expansion.