sed: Insert Lines Before and After a Pattern Match
Use sed to insert text before or after a line that matches a pattern, without opening the file in an editor.
Insert a Line Before a Match
# Insert "NEW LINE" before every line containing "PATTERN"
sed -i '/PATTERN/i NEW LINE' file.txt
# Example: insert a comment before a config directive
sed -i '/^ServerName/i # Primary server name' /etc/apache2/apache2.conf
Insert a Line After a Match
# Insert "NEW LINE" after every line containing "PATTERN"
sed -i '/PATTERN/a NEW LINE' file.txt
# Example: add a directive after the opening VirtualHost tag
sed -i '/<VirtualHost \*:80>/a\ ServerAdmin admin@example.com' site.conf
Replace a Line Containing a Pattern
# Replace entire matching line
sed -i '/PATTERN/c\NEW CONTENT' file.txt
Preview Before Saving (Dry Run)
# Show result without modifying the file (omit -i)
sed '/PATTERN/i NEW LINE' file.txt
Remove Windows Line Endings (^M / \r) from Linux Files
Files transferred from Windows to Linux often contain \r\n (CRLF) line endings instead of Unix \n (LF). The ^M characters visible in editors are the carriage return (\r). Here's how to remove them.
Remove ^M from a Single File with sed
sed -i -e 's/
$//' filename.sh
Remove ^M Using dos2unix
sudo apt-get install -y dos2unix
dos2unix filename.sh
# Convert multiple files
dos2unix *.sh
Remove ^M from All PHP Files Recursively
find . -type f -name "*.php" -exec dos2unix {} \;
# or with sed:
find . -type f -name "*.php" -exec sed -i -e 's/
$//' {} \;
Verify
# Check for carriage returns
file filename.sh
# "ASCII text" = clean; "CRLF line terminators" = needs fixing
cat -A filename.sh | head -5
# Clean lines end with $; Windows lines end with ^M$
Bulk Replace Domain Name in Files with sed and grep
How to find and replace an old domain name across multiple files in a directory, excluding specific subdirectories like git metadata or media files.
Replace Domain in All Files (with Exclusions)
grep -rl "https://olddomain.com" . \
--exclude-dir=.git \
--exclude-dir=media \
| xargs sed -i 's,https://olddomain.com,https://newdomain.com,g'
Preview Changes First (Dry Run)
# See which files contain the old domain
grep -rl "https://olddomain.com" . --exclude-dir=.git
# See the actual lines that will change
grep -rn "https://olddomain.com" . --exclude-dir=.git
Replace in a Specific File Type
# Only PHP files
grep -rl "olddomain.com" . --include="*.php" \
| xargs sed -i 's/olddomain\.com/newdomain.com/g'
Notes
- Use commas (
,) instead of slashes in the sed pattern when URLs contain slashes.
- Always do a dry run (no
-i) first to preview changes before modifying files.
- Back up the directory before bulk replacements:
cp -r . ../backup
Combine Multiple sed Substitutions in One Command
When you need to apply multiple sed substitutions to a file, use the -e flag to chain them in a single command instead of running sed multiple times.
Using Multiple -e Flags
sed -i -e 's/File//g' -e 's/MINvac.pdb//g' input.txt
Using a Semicolon Separator
sed -i 's/foo/bar/g; s/baz/qux/g' input.txt
Using a sed Script File
# Create a script file with multiple commands
cat > fix.sed << 'EOF'
s/File//g
s/MINvac.pdb//g
s/old_hostname/new_hostname/g
EOF
# Apply the script
sed -i -f fix.sed input.txt
Apply to All Files in a Directory
find . -name "*.txt" -exec sed -i -e 's/foo/bar/g' -e 's/baz/qux/g' {} \;
Preview Without Modifying
# Omit -i to print to stdout
sed -e 's/File//g' -e 's/MINvac.pdb//g' input.txt