Shell Scripting SED Real-World Advanced May 2026

Shell Scripting Advanced SED: Real-World Transformations

Production SED patterns — log sanitisation and redaction, Nginx/Apache config patching, Dockerfile and YAML editing, SQL script transformation, Markdown processing, and a complete data migration SED pipeline.

This page closes the Advanced SED section with the patterns that appear in real operations work — the kind of transformations you reach for during deployments, migrations, and incident response. Every example here solves a specific production problem using SED as the right tool for the job.

BASH
# ── Redact passwords from logs ────────────────────────────
sed -E 's/(password|passwd|secret|token|api.?key)=[^& \t]*/\1=REDACTED/gI'

# ── Mask IP addresses ─────────────────────────────────────
sed -E 's/\b([0-9]{1,3}\.){3}[0-9]{1,3}\b/x.x.x.x/g'

# ── Mask email addresses ──────────────────────────────────
sed -E 's/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/***@***.com/g'

# ── Mask credit card numbers ──────────────────────────────
sed -E 's/[0-9]{4}[- ]?[0-9]{4}[- ]?[0-9]{4}[- ]?([0-9]{4})/****-****-****-\1/g'

# ── Strip ANSI colour codes from logs ─────────────────────
sed -E 's/\x1B\[[0-9;]*[mKHF]//g'

# ── Complete log sanitiser pipeline ──────────────────────
sed -E '
  s/(password|secret|token)=[^& \t]*/\1=REDACTED/gI
  s/\b([0-9]{1,3}\.){3}[0-9]{1,3}\b/x.x.x.x/g
  s/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+/***@***/g
  s/\x1B\[[0-9;]*[mK]//g
' /var/log/myapp/app.log > /var/log/myapp/app.sanitised.log
BASH
# ── Enable/disable Nginx site ────────────────────────────
# Comment out a server block
sed -i '/^server {/,/^}/{s/^/#/}' /etc/nginx/sites-available/myapp

# Update upstream server
sed -i 's|server 127.0.0.1:8080|server 127.0.0.1:8081|g' \
  /etc/nginx/conf.d/upstream.conf

# ── Dockerfile version bumps ──────────────────────────────
sed -i -E 's|^FROM node:[0-9.]+-alpine|FROM node:22-alpine|' Dockerfile
sed -i -E 's|^FROM python:[0-9.]+|FROM python:3.12|' Dockerfile

# ── YAML value updates (simple key: value pairs) ──────────
sed -i -E 's|^(  image: myapp:)[^ ]+|\1v2.1.0|' docker-compose.yml
sed -i -E 's|^(replicas:) [0-9]+|\1 5|' k8s/deployment.yaml

# ── Update Kubernetes resource limits ─────────────────────
sed -i '/resources:/,/limits:/{
  s/memory: "512Mi"/memory: "1Gi"/
  s/cpu: "250m"/cpu: "500m"/
}' k8s/deployment.yaml

# ── Add a label to Kubernetes manifest ────────────────────
sed -i '/^metadata:/a\  labels:\n    version: "2.1.0"' k8s/deployment.yaml

# ── Environment variable substitution in Helm values ──────
sed -E "s|\\\${DB_HOST}|${DB_HOST}|g" values.yaml.template > values.yaml
BASH
# ── Convert MySQL dump to PostgreSQL ──────────────────────
sed -E '
  s/`([^`]+)`/"\1"/g          # backtick identifiers → double quotes
  s/ ENGINE=\S+//g             # remove ENGINE= clauses
  s/ AUTO_INCREMENT=[0-9]+//g  # remove AUTO_INCREMENT
  s/ unsigned//g               # remove unsigned type modifier
  s/\bTINYINT\b/SMALLINT/g     # MySQL → PostgreSQL types
  s/\bDATETIME\b/TIMESTAMP/g
  s/\bLONGTEXT\b/TEXT/g
  /^SET /d                     # remove MySQL SET statements
  /^\/\*!.*\*\/;/d             # remove MySQL-specific comments
' dump.sql > dump_pg.sql

# ── Add schema prefix to all table references ─────────────
sed -E 's/\b(FROM|JOIN|INTO|UPDATE|TABLE) ([a-zA-Z_][a-zA-Z0-9_]*)\b/\1 myschema.\2/gI' \
  migration.sql

# ── Extract only CREATE TABLE statements ──────────────────
sed -n '/^CREATE TABLE/,/^;/p' dump.sql

# ── Comment out DROP statements for safety ────────────────
sed -i '/^DROP TABLE/s/^/-- DISABLED: /' migration.sql

# ── Batch rename a table across an entire SQL file ────────
sed -i 's/\bold_table_name\b/new_table_name/g' schema.sql
BASH
#!/usr/bin/env bash
# migrate_configs.sh — Fleet-wide v1→v2 config migration using SED

set -euo pipefail

BACKUP_DIR="/opt/myapp/config.backup.$(date +%Y%m%d_%H%M%S)"
CONFIG_DIR="/etc/myapp"
CHANGES=0

mkdir -p "${BACKUP_DIR}"

echo "  Backing up configs to ${BACKUP_DIR}..."
cp -r "${CONFIG_DIR}/"* "${BACKUP_DIR}/"

echo "  Applying v1→v2 migrations..."

for cfg in "${CONFIG_DIR}"/*.env; do
  before=$(md5sum "${cfg}" | cut -d' ' -f1)

  sed -i -E '
    # Key renames
    s/^DB_SERVER=/DB_HOST=/
    s/^MYSQL_PASSWORD=/DB_PASS=/
    s/^APP_DEBUG=true/LOG_LEVEL=DEBUG/
    s/^APP_DEBUG=false/LOG_LEVEL=INFO/

    # Value normalisation
    s/^DB_PORT=3307$/DB_PORT=3306/

    # Remove deprecated keys
    /^LEGACY_AUTH=/d
    /^OLD_SESSION_KEY=/d

    # Add missing defaults
    /^DB_TIMEOUT=/!{
      /^DB_/a\DB_TIMEOUT=30
    }
  ' "${cfg}"

  after=$(md5sum "${cfg}" | cut -d' ' -f1)
  [[ "${before}" != "${after}" ]] && { (( CHANGES++ )); echo "  ✔ ${cfg}"; }
done

echo "  Migration complete: ${CHANGES} files changed"
echo "  Backup: ${BACKUP_DIR}"
sed — real-world pipeline
vriddh@prod-01:~/scripts$./migrate_configs.sh
Backing up configs to /opt/myapp/config.backup.20260501_101402...
Applying v1→v2 migrations...
✔ /etc/myapp/prod.env
✔ /etc/myapp/staging.env
Migration complete: 2 files changed
✔ Real-world SED — Always take a backup before any in-place batch edit. Use grep -rl pattern | xargs sed -i to skip unchanged files. Use md5sum to detect whether a file actually changed. Test the SED expression on a single file before running fleet-wide. The combination of SED + find + xargs is the fastest way to apply consistent text transformations across dozens of servers and hundreds of config files.