Replace strings in files with sed, the bash command

Sed is a stream editor, meaning you can search and replace strings in files and use regex if needed. The changes can be done "in place" or save the modified content to a renamed file. This is especially good for replacing placeholder values in configuration files.

There’s a million things to sed, see the man page. This post looks into how to replace simple string in files.


Let’s imagine a file called metamorfosis.txt, with a content:

One morning, when Gregor Samsa woke from troubled 
dreams, he found himself transformed in his bed into 
a horrible vermin.

Lets replace the “vermin” with a “pony” and copy the file under different name:

$ sed 's/vermin/pony/g' metamorphosis.txt > ponymorphosis.txt

You can run that in the prompt, or put it into a file and run the file.

Replace in place

-i for “in place”, it means that no copy of the file will be created.

$ sed -i 's/vermin/pony/g' metamorphosis.txt

Using variables as replace and search values

Variables can be used just as well, only they need to be interpolated and the first sed argument needs to be double quoted, instead of singular. Here’s it wrapped into a function:

ponyfyer() {
    local search=$1
    local replace=$2
    # Note the double quotes
    sed -i "s/${search}/${replace}/g" metamorphosis.txt

This is the time to note that there are two flavours of sed, the Linux sed, and the FreeBSD sed. As OS X branched from Next, and Next came from BSD, uses OS X the FreeBSD flavoured sed. Which is a bit different, see the FreeBSD man page for details.

The BSD sed needs a backup file when replacing in place, we don’t really want to use a backup file, so we have define an empty backup file. Note the empty pair of quotes after the -i:

ponyfyer() {
    local search=$1
    local replace=$2
    sed -i "" "s/${search}/${replace}/g" metamorphosis.txt

Otherwise it’ll throw an error:

sed: 1: "/Users/user/path/ponyf ...": extra characters at the end of h command

Now on we’re gonna use the OS X sed.

Replace an array of values

Let’s pick less silly example, a config file where we replace %%placeholder%% values. Below is the contents of the config file:

# config.php
define( 'DB_NAME', '%%DB_NAME%%' );
define( 'DB_USER', '%%DB_USER%%' );
define( 'DB_PASSWORD', '%%DB_PASSWORD%%' );
define( 'DB_HOST', '%%DB_HOST%%' );

And this is the contents of the script file:

# Associative array where key represents a search string,
# and the value itself represents the replace string.
declare -A confs

configurer() {
    # Loop the config array
    for i in "${!confs[@]}"
        # Note the "" after -i, needed in OS X
        sed -i "" "s/${search}/${replace}/g" config.php

We end up with readily configured file:

# config.php
define( 'DB_NAME', 'bobs_db' );
define( 'DB_USER', 'bob' );
define( 'DB_PASSWORD', 'hammertime' );
define( 'DB_HOST', 'localhost' );

Note: when using a loop, we have to use the in place option.

Replacing values with forward slashes in them

If a value is, say, a URL and it has / in it, then sed returns an error similar to this:

sed: 1: "s/%%PRODUCTION_DEPLOY_T ...": bad flag in substitute command: 'v'

Or the almost identical:

sed: 1: "s/%%APP_REPO%%/git@gith ...": bad flag in substitute command: 'e'

There’s two ways to deal with this:

  1. Escape the values, more here
  2. Don’t use forward slash as a separator in sed

Let’s concentrate on the latter. The separator doesn’t have to be /, it can be anything, like a pipe |, for instance:

sed -i "" "s|${search}|${replace}|g" config.php

The character can be anything, as long as all the separators are the same:

sed -i "" "s♥${search}♥${replace}♥g" config.php


sed is pretty powerful, like cooking with gas.


  • Thank you so much for this! It just helped me stop loosing my mind!!!

  • Anonymous says:

    Thank you very much. This really helped me out in a pinch.

  • Starlord says:

    Nice article, but are you sure nobody will notice what you wrote in the footer ;).
    yadda yadda.

    Kind Regards.

  • each time i used to readd smaloler articles which as well clear their motive, and that is also happening with this piece of writing which I am reading here.

  • Useful and concise!

  • Anonymous says:

    Can we somehow read the values that has to be placed from another file? All these values confs=(
    to be in param.file for example.

    and then change the config.php

  • Harish says:

    Can you please help me on how to replace a line in an existing file with a new line.

    old line: daemon /opt/Tanium/TaniumClient/TaniumClient
    new line: daemon runuser -u taniumclient /opt/Tanium/TaniumClient/TaniumClient

    eg file

    start() {
    echo -n $”Starting $prog:”
    daemon /opt/Tanium/TaniumClient/TaniumClient
    [ “$RETVAL” = 0 ] && touch /var/lock/subsys/$prog
    return $RETVAL


    start() {
    echo -n $”Starting $prog:”
    daemon runuser -u taniumclient /opt/Tanium/TaniumClient/TaniumClient
    [ “$RETVAL” = 0 ] && touch /var/lock/subsys/$prog
    return $RETVAL

    Thanks very much

  • inukaze says:

    Hi there how i can replace using sed the text


    i try :
    sed -i “s|${root=/dev/sda3}|${blkid | grep sda3 | awk ‘{print $3}’ | sed ‘s/[=UID].//’ | sed ‘s/[“].//’}|g” /boot/grub/grub.cfg

    i want to put blkid + sed, output. but says bad sustitution. how i can do it?

  • Prasa says:

    I have a multiple files in a directory eg:
    Line 3 of all text files in the directory is as follows:

    consumer[location].userid= constant

    I want to replace the word “location” with the respective filename with out extension , in the third line of each file eg: as

    consumer[a01].userid= constant ——— for a01.txt

    consumer[a02].userid= constant ——— for a03.txt


    Can you please help?

  • Loïc Prieto says:

    Hi there! Thanks for the article, it is very helpful!

    Just a quick comment: in the for loop where you use the db params array, you use a different name for the loop variable:
    confs_wp instead of confs.
    replace=${confs_wp[$i]} => . replace=${confs[$i]}

    Or is there something i’m not taking into account?

Club-Mate, the beverage →