Pipeline Chains
grep | sed — find lines then transform
cat <<'EOF' > /tmp/syslog.txt
Apr 11 10:01:23 server sshd[1234]: Accepted publickey for evan
Apr 11 10:01:45 server sshd[1235]: Failed password for root
Apr 11 10:02:01 server crond[5678]: (root) CMD (run-parts)
Apr 11 10:02:30 server sshd[1236]: Failed password for admin
Apr 11 10:03:00 server sshd[1237]: Accepted publickey for deploy
EOF
# Find failed attempts, extract just user and timestamp
grep 'Failed password' /tmp/syslog.txt | sed -E 's/.*(\S+ \S+ \S+).*Failed password for (\S+)/\1 FAILED: \2/'
find | xargs sed — bulk in-place edit across files
# Create test files
mkdir -p /tmp/sed-bulk
echo 'version: 1.0.0' > /tmp/sed-bulk/a.conf
echo 'version: 1.0.0' > /tmp/sed-bulk/b.conf
echo 'version: 1.0.0' > /tmp/sed-bulk/c.conf
# Bulk update version across all .conf files
find /tmp/sed-bulk -name '*.conf' -print0 | xargs -0 sed -i 's/version: 1.0.0/version: 2.0.0/'
# Verify
cat /tmp/sed-bulk/a.conf /tmp/sed-bulk/b.conf /tmp/sed-bulk/c.conf
sed | awk — sed cleans, awk processes
cat <<'EOF' > /tmp/messy-csv.txt
Name , Age , Role
Alice , 30 , Admin
Bob , 25 , User
Charlie , 35 , Admin
EOF
# sed strips leading whitespace and spaces around commas; awk processes fields
sed 's/^[[:space:]]*//;s/[[:space:]]*,[[:space:]]*/,/g' /tmp/messy-csv.txt | \
awk -F, 'NR>1 && $3=="Admin" {print $1, "is", $2, "years old"}'
curl | sed — extract content from HTML
# Simulate HTML response (no network needed)
cat <<'EOF' > /tmp/page.html
<html>
<head><title>Test Page</title></head>
<body>
<h1>Welcome to Domus Digitalis</h1>
<p>Infrastructure documentation</p>
<a href="https://docs.domusdigitalis.dev">Docs</a>
<a href="https://github.com/domus">GitHub</a>
</body>
</html>
EOF
# Extract href URLs from anchor tags
sed -n 's/.*href="\([^"]*\)".*/\1/p' /tmp/page.html
diff with process substitution — compare transformed versions
cat <<'EOF' > /tmp/config-v1.txt
host = old-server
port = 8080
debug = true
workers = 2
EOF
cat <<'EOF' > /tmp/config-v2.txt
host = new-server
port = 9090
debug = false
workers = 4
EOF
# Compare after normalizing both — strip whitespace around =
diff <(sed 's/ *= */=/' /tmp/config-v1.txt) <(sed 's/ *= */=/' /tmp/config-v2.txt)
sed inside shell loops — process multiple patterns
cat <<'EOF' > /tmp/template.txt
Hello USER_NAME,
Your server SERVER_HOST is running on port SERVER_PORT.
Environment: SERVER_ENV
EOF
# Loop over key-value pairs to expand template
cp /tmp/template.txt /tmp/rendered.txt
for pair in 'USER_NAME/Evan' 'SERVER_HOST/modestus-aw' 'SERVER_PORT/443' 'SERVER_ENV/production'; do
key="${pair%%/*}"
val="${pair#*/}"
sed -i "s/${key}/${val}/g" /tmp/rendered.txt
done
cat /tmp/rendered.txt
sed output as shell variable
cat <<'EOF' > /tmp/version.txt
application_name: domus-api
version: 3.2.1-beta
release_date: 2026-04-11
EOF
# Capture sed output into a variable
version=$(sed -n 's/^version: //p' /tmp/version.txt)
echo "Current version: ${version}"
# Use in conditional
major=$(echo "${version}" | sed -E 's/^([0-9]+)\..*/\1/')
echo "Major version: ${major}"
sed + tee — transform and save while continuing pipeline
cat <<'EOF' > /tmp/raw-log.txt
2026-04-11 ERROR disk full on /dev/sda1
2026-04-11 INFO backup completed
2026-04-11 ERROR connection refused to db
2026-04-11 WARN high memory usage
2026-04-11 ERROR timeout on api call
EOF
# sed extracts errors; tee saves to file; wc counts them
sed -n '/ERROR/p' /tmp/raw-log.txt | tee /tmp/errors-only.txt | wc -l
cat /tmp/errors-only.txt
sed in pipeline with sort and uniq — log analysis
cat <<'EOF' > /tmp/access.log
10.50.1.20 GET /api/users 200
10.50.1.50 POST /api/auth 401
10.50.1.20 GET /api/status 200
192.168.1.1 GET /api/users 200
10.50.1.50 GET /api/health 200
10.50.1.20 POST /api/auth 401
EOF
# Extract IPs with failed auth, count occurrences
sed -n '/ 401$/s/ .*//p' /tmp/access.log | sort | uniq -c | sort -rn