Tricks in bash

From Computational Biophysics and Materials Science Group
Jump to: navigation, search

Batch Search and Replace in Multiple Files

Two simple, rather elegant, solutions:

perl -pi -w -e ‘s/wrong/right/g;’ *.html
Replaces all instances of ‘wrong’ with ‘right’ in html files within the current working directory.

grep -rl “wrong” /home/jerrywaller | xargs sed -i ‘s|wrong|right|g’
Recursively replaces ‘wrong’ with ‘right’ within the designated directory.

Just make sure you use plain single and double quotation marks, and not the smart quotes that may show up in the formatting above. Hat tip to the author and commenters here and here.

You could also use find and sed, but I find that this little line of perl works nicely.

perl -pi -w -e 's/search/replace/g;' *.php
-e means execute the following line of code.
-i means edit in-place
-w write warnings
-p loop

Example I had the following style sheet in a section:

<link rel="stylesheet" type="text/css" href="../includes/style.css">

and I wanted the following instead:

<link rel="stylesheet" type="text/css" href="admin.css">

As each expression is a regular expression you've got to escape the special characters such as forward slash and .\.\.\/includes\/style\.css

So the final line of code ends up as

perl -pi -w -e 's/\.\.\/includes\/style\.css/admin\.css/g;' *.php

sed/awk

These two commands are so powerful that you must learn especially when you are dealing with data file with millions lines.

Here is a very detail introduction on sed, you may not have to read it thoroughly but it covers most of the situation that you may encounter.

Grep only the first n columns

Commands:

cat old.dat | awk '{print $1 "\t" $2 "\t" $3}' > new.dat

Replace some strings in your lines

Commands:

cat data | grep 'ABC'| grep -v "XYZ" | sed 's/ABC/DEF/g'

What the above will do: grep only lines containing "ABC", then grep lines without "XYZ", then replace "ABC" with "DEF"

Insert a new line after every n lines

Here is an accurate answer to the question on StackExchange, I found the situation often to encounter but the solution is surprisingly difficult to find.

Basically, the command will be (I personally prefer the awk version):

awk ' {print;} NR % 40 == 0 {print "Text Here";}' old.dat > new.dat

Modify the number and string inside "" accordingly. Remember to redirect to a new datafile, otherwise it will only print out on the screen.

Delete multiple lines containing a string

sed -i '/pattern to match/d' ./infile

in which the option -i will directly modify the file. Using wildcase (*), you could modify multiple files at a time.

vi editor

Insert a word/text in the beginning of each line

Again it is another discussion at StackExchange.

Commands:

:%s/^/Text Here/