[bash] Find and Replace Inside a Text File from a Bash Command

What's the simplest way to do a find and replace for a given input string, say abc, and replace with another string, say XYZ in file /tmp/file.txt?

I am writting an app and using IronPython to execute commands through SSH — but I don't know Unix that well and don't know what to look for.

I have heard that Bash, apart from being a command line interface, can be a very powerful scripting language. So, if this is true, I assume you can perform actions like these.

Can I do it with bash, and what's the simplest (one line) script to achieve my goal?

This question is related to bash ssh replace scripting ironpython

The answer is


You can use sed:

sed -i 's/abc/XYZ/gi' /tmp/file.txt

You can use find and sed if you don't know your filename:

find ./ -type f -exec sed -i 's/abc/XYZ/gi' {} \;

Find and replace in all Python files:

find ./ -iname "*.py" -type f -exec sed -i 's/abc/XYZ/gi' {} \;

You may also use the ed command to do in-file search and replace:

# delete all lines matching foobar 
ed -s test.txt <<< $'g/foobar/d\nw' 

See more in "Editing files via scripts with ed".


File manipulation isn't normally done by Bash, but by programs invoked by Bash, e.g.:

perl -pi -e 's/abc/XYZ/g' /tmp/file.txt

The -i flag tells it to do an in-place replacement.

See man perlrun for more details, including how to take a backup of the original file.


Try the following shell command:

find ./  -type f -name "file*.txt" | xargs sed -i -e 's/abc/xyz/g'

I found this thread among others and I agree it contains the most complete answers so I'm adding mine too:

  1. sed and ed are so useful...by hand. Look at this code from @Johnny:

    sed -i -e 's/abc/XYZ/g' /tmp/file.txt
    
  2. When my restriction is to use it in a shell script, no variable can be used inside in place of "abc" or "XYZ". The BashFAQ seems to agree with what I understand at least. So, I can't use:

    x='abc'
    y='XYZ'
    sed -i -e 's/$x/$y/g' /tmp/file.txt
    #or,
    sed -i -e "s/$x/$y/g" /tmp/file.txt
    

    but, what can we do? As, @Johnny said use a while read... but, unfortunately that's not the end of the story. The following worked well with me:

    #edit user's virtual domain
    result=
    #if nullglob is set then, unset it temporarily
    is_nullglob=$( shopt -s | egrep -i '*nullglob' )
    if [[ is_nullglob ]]; then
       shopt -u nullglob
    fi
    while IFS= read -r line; do
       line="${line//'<servername>'/$server}"
       line="${line//'<serveralias>'/$alias}"
       line="${line//'<user>'/$user}"
       line="${line//'<group>'/$group}"
       result="$result""$line"'\n'
    done < $tmp
    echo -e $result > $tmp
    #if nullglob was set then, re-enable it
    if [[ is_nullglob ]]; then
       shopt -s nullglob
    fi
    #move user's virtual domain to Apache 2 domain directory
    ......
    
  3. As one can see if nullglob is set then, it behaves strangely when there is a string containing a * as in:

    <VirtualHost *:80>
     ServerName www.example.com
    

    which becomes

    <VirtualHost ServerName www.example.com
    

    there is no ending angle bracket and Apache2 can't even load.

  4. This kind of parsing should be slower than one-hit search and replace but, as you already saw, there are four variables for four different search patterns working out of one parse cycle.

The most suitable solution I can think of with the given assumptions of the problem.


I was surprised when I stumbled over this...

There is a replace command which ships with the "mysql-server" package, so if you have installed it try it out:

# replace string abc to XYZ in files
replace "abc" "XYZ" -- file.txt file2.txt file3.txt

# or pipe an echo to replace
echo "abcdef" |replace "abc" "XYZ"

See man replace for more on this.


Be careful if you replace URLs with "/" character.

An example of how to do it:

sed -i "s%http://domain.com%http://www.domain.com/folder/%g" "test.txt"

Extracted from: http://www.sysadmit.com/2015/07/linux-reemplazar-texto-en-archivos-con-sed.html


You can use rpl command. For example you want to change domain name in whole php project.

rpl -ivRpd -x'.php' 'old.domain.name' 'new.domain.name' ./path_to_your_project_folder/  

This is not clear bash of cause, but it's a very quick and usefull. :)


If the file you are working on is not so big, and temporarily storing it in a variable is no problem, then you can use Bash string substitution on the whole file at once - there's no need to go over it line by line:

file_contents=$(</tmp/file.txt)
echo "${file_contents//abc/XYZ}" > /tmp/file.txt

The whole file contents will be treated as one long string, including linebreaks.

XYZ can be a variable eg $replacement, and one advantage of not using sed here is that you need not be concerned that the search or replace string might contain the sed pattern delimiter character (usually, but not necessarily, /). A disadvantage is not being able to use regular expressions or any of sed's more sophisticated operations.


Bash, like other shells, is just a tool for coordinating other commands. Typically you would try to use standard UNIX commands, but you can of course use Bash to invoke anything, including your own compiled programs, other shell scripts, Python and Perl scripts etc.

In this case, there are a couple of ways to do it.

If you want to read a file, and write it to another file, doing search/replace as you go, use sed:

    sed 's/abc/XYZ/g' <infile >outfile

If you want to edit the file in place (as if opening the file in an editor, editing it, then saving it) supply instructions to the line editor 'ex'

    echo "%s/abc/XYZ/g
    w
    q
    " | ex file

Example is like vi without the fullscreen mode. You can give it the same commands you would at vi's : prompt.


To edit text in the file non-interactively, you need in-place text editor such as vim.

Here is simple example how to use it from the command line:

vim -esnc '%s/foo/bar/g|:wq' file.txt

This is equivalent to @slim answer of ex editor which is basically the same thing.

Here are few ex practical examples.

Replacing text foo with bar in the file:

ex -s +%s/foo/bar/ge -cwq file.txt

Removing trailing whitespaces for multiple files:

ex +'bufdo!%s/\s\+$//e' -cxa *.txt

Troubleshooting (when terminal is stuck):

  • Add -V1 param to show verbose messages.
  • Force quit by: -cwq!.

See also:


This is an old post but for anyone wanting to use variables as @centurian said the single quotes mean nothing will be expanded.

A simple way to get variables in is to do string concatenation since this is done by juxtaposition in bash the following should work:

sed -i -e "s/$var1/$var2/g" /tmp/file.txt

You can use python within the bash script too. I didn't have much success with some of the top answers here, and found this to work without the need for loops:

#!/bin/bash
python
filetosearch = '/home/ubuntu/ip_table.txt'
texttoreplace = 'tcp443'
texttoinsert = 'udp1194'

s = open(filetosearch).read()
s = s.replace(texttoreplace, texttoinsert)
f = open(filetosearch, 'w')
f.write(s)
f.close()
quit()

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to ssh

Starting ssh-agent on Windows 10 fails: "unable to start ssh-agent service, error :1058" How to solve "sign_and_send_pubkey: signing failed: agent refused operation"? key_load_public: invalid format ssh connection refused on Raspberry Pi Getting permission denied (public key) on gitlab Verify host key with pysftp Can't connect to Postgresql on port 5432 Checkout Jenkins Pipeline Git SCM with credentials? How to open remote files in sublime text 3 how to setup ssh keys for jenkins to publish via ssh

Examples related to replace

How do I find and replace all occurrences (in all files) in Visual Studio Code? How to find and replace with regex in excel How to replace text in a column of a Pandas dataframe? How to replace negative numbers in Pandas Data Frame by zero Replacing few values in a pandas dataframe column with another value How to replace multiple patterns at once with sed? Using tr to replace newline with space replace special characters in a string python Replace None with NaN in pandas dataframe Batch script to find and replace a string in text file within a minute for files up to 12 MB

Examples related to scripting

What does `set -x` do? Creating an array from a text file in Bash Windows batch - concatenate multiple text files into one Raise error in a Bash script How do I assign a null value to a variable in PowerShell? Difference between ${} and $() in Bash Using a batch to copy from network drive to C: or D: drive Check if a string matches a regex in Bash script How to run a script at a certain time on Linux? How to make an "alias" for a long path?

Examples related to ironpython

How do I run a Python script from C#? Find and Replace Inside a Text File from a Bash Command