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"