views:

4648

answers:

4

Whats the simplest way to do a find and replace for a given input string, say "abc", and replace with another string, say "XYZ" - the the file, /tmp/file.txt?

I am wrtting an app and using IronPython to execute commands through SSH - but I dont know unix that well and dont know what I am looking for.

I have heard that Bash script, 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 this.

Can I do it with bash, and whats the simplest (one line) script to do it?

+5  A: 

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 do do in-place replacement.

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

Alnitak
The purist in me says you can't be sure Perl will be available on the system. But that's very seldom the case nowadays. Perhaps I'm showing my age.
slim
+3  A: 

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

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

slim
Alnitak
My bad. It needed the % (meaning "for all lines") before s. Fixed.
slim
+13  A: 

The easiest way is to use sed (or perl):

sed -ie 's/abc/XYZ/g' /tmp/file.txt

Which will invoke sed to do an inplace edit. This can be called from bash.

If you really really want to use just bash, then the following can work:

while read a ; do echo ${a//abc/XYZ} ; done < /tmp/file.txt > /tmp/file.txt.t ; mv /tmp/file.txt{.t,}

This loops over each line, doing a substitution, and writing to a temporary file (don't want to clobber the input). The move at the end just moves temporary to the original name.

johnny
Except that invoking mv is pretty much as 'non Bash' as using sed. I nearly said the same of echo, but it's a shell builtin.
slim
Nice - I don't think sed had a "-i" option last time I had call to check the man page :)
Alnitak
I didn't know about the -i option to sed. Very handy! Upvote for that.
slim
A: 

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

# cf. http://bash-hackers.org/wiki/doku.php?id=howto:edit-ed 

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