Replace
Find and replace text in a file, a variable or a string
Using shell parameter expansion
Syntax: ${VARNAME//FIND/REPLACE}. The // is necessary for global replacement.
$ x=foo_bar_baz_buzz
$ echo ${x//_/-}
foo-bar-baz-buzz
$ echo ${x/_/-}
foo-bar_bazz_buzz
Using sed and a regex pattern
Regex substitution is used in this guide. Test your pattern at regex101.com.
Syntax: s/FIND/REPLACE/g.
The g is for global and is more useful for files and multi-line strings than for one-line strings.
Example:
s/foo/bar/g
Use g for global. Add I after g for case insensitive flag.
Some characters must be escaped such as with backslash.
Replace word
Using a string.
$ echo 'football' | sed 's/foo/bar/g'
bartball
$ echo 'football' | sed 's/foo/bar/g'
tball
Using a variable.
$ x='football'
$ echo $x | sed 's/foo/bar/g'
bartball
Replace newline character
Given text:
$ echo 'Hello\nworld'
Hello
world
Note that those also remove a trailing newline.
Note you don’t need to escape \n as \\n.
sed
Using sed. This doesn’t work on the macOS sed though.
$ echo 'Hello\nworld' | sed 's/\n/ /'
Hello world
tr
Using tr.
$ echo 'Hello\nworld' | tr '\n' ' '
Hello world
Replace character with a newline character
Use \ followed by pressing enter. Using \n doesn’t seem to work here.
sed
$ echo 'Hello,World' | sed 's/,/\
/g'
Hello
World
tr
Both of these work.
$ echo "Hello:world" | tr ':' '\n'
Hello
world
$ echo "Hello:world" | tr ':' '
'
Hello
world
Make sure that the 2nd argument for tr is ' followed by enter - if you press space and then enter then it doesn’t work.
Replace inline in file with backup flag
The default use of sed will just print, without saving to a file.
sed 's/foo/bar/g' file.txt
So use the inline flag to update the file.
# Linux
sed -i'' 's/foo/bar/g' file.txt
# macOS
sed -i '' 's/foo/bar/g' file.txt
See more info in my sed guide.
Replace word in file
Replace foo with bar in file.txt and print to the console.
sed -i 's/foo/bar/g' file.txt
From tutorial
Replace multiple words in a file
Use multiple replacements in one command
Separate with semicolon
sed -i 's/foo/bar/g; s/fizz/buzz/g' file.txt
Separate with newline
sed -i 's/foo/bar/g
s/fizz/buzz/g
' file.txt
Advanced
For more control, you can use you can use an intermediate term. Like the arbitrary ~~ below.
Here we rename foo to bar but preserve instances of food.
sed -i 's/food/~~/g; s/foo/bar/g; s/~~/food/g' file.txt
Note there may be a cleaner way to do this, such a with regex in the console or your IDE. Maybe with grep or find.
Replace a word in multiple files
Replace foo with bar in all files in a directory.
sed -i 's/foo/bar/g' *
sed -i 's/foo/bar/g' foo/*
I don’t think it goes into a directory though and it gives errors on processing directory. So that is why using find and setting type as file as later in this guide is useful.
Delete lines
Delete an entire line matching pattern.
sed
$ sed -i '' '/foo/d' file.txt
Use the reverse match.
$ sed -i '' -n '/foo/!p' file.txt
tr
Using --delete flag.
$ tr -d 'foo' < file.txt
awk
Use the reverse match.
Note that > will start overwriting immediately so you need a temp file.
$ awk '!/foo/' file.txt > temp && mv temp file.txt
grep
Use the reverse match.
$ grep -v "foo" file.txt > temp && mv temp file.txt
Replace and output a new file
$ sed 's/spam/eggs/g' foo.html > bar.html
Combine sed and find
Use find to find files and replace in-line, while the sed part is your transformation.
This is useful to apply to files only since sed will give an error on in-place replacements against directories. Also, find is suited for finding files nested in directories.
General:
$ find . -type f -exec sed -i 'PATTERN' {} \;
e.g.
$ find . -type f -exec sed -i 's/foo/bar/g' {} \;
Replace tabs with 2 spaces in a directory:
$ find . -type f -exec sed -i 's/\t/ /g' {} \;
From StackOverflow.
You can narrow down the name. Here is a glob. Make sure to use a star that is quoted. Also the star glob will not match hidden directories - this will help you avoid accidentally updating and breaking .git.
$ find . -type f -name '*' -exec 'sed -i .bak -e "PATTERN" {} +'
$ find . -exec sed -i '' -e 'PATTERN' {} \;
-e command
Append the editing commands specified by the command argument to the list of commands.
Or reverse the order so find is used by sed. I found this easier than the syntax above which I copied but kept getting errors on.
$ sed -i 's/foo/bar/g' $(find . -type f)
Install sed
If you are used to the GNU (Linux) sed, you can set it up on macOS too.
$ brew install gnu-sed
Add to .bashrc or .zshrc to make is accesible.
export PATH="/usr/local/opt/gnu-sed/libexec/gnubin:$PATH"