3

I need to edit lines in a file using sed. Now the problem is I am replacing a particular pattern with a combination of text and number. This number is a variable which keeps on incrementing for every subsequent line. Now as sed executes the command for all lines in one go, it is replacing the pattern found with the text and fixed number (i.e initial value of number).

For example:

k = 10
sed "s/raj/ram${k++}/"

3 Answers 3

2

If your file is pretty small, this might work:

#!/bin/bash
for n in {1..40}
do
    sed -i $n's/raj/ram'$n'/' file
done 

It iterates over the file 40 times, and always replaces just 1 line. If you want to increment a counter not by line number, but by the number of lines you changed, you have to do it differently, with 2 variables, but the sed-command would be similar - n wouldn't be set by the loop.

sed -i changes the file in place, so if you want to keep the original, you have to make a copy first.

It can be done in a oneliner, if you prefer that:

for n in {1..40}; do sed -i $n's/raj/ram '$n'/' file ; done

Choosing the correct size instead of 40 automatically is possible too.

3
  • 2
    You can use $(seq $(wc -l <input.txt)) instead of {1..40} for all lines of a specific file.
    – ceving
    Commented Aug 30, 2011 at 11:04
  • Horribly inefficient on large files...
    – Kusalananda
    Commented Sep 9, 2011 at 21:30
  • Yes, but no problem for small ones. Why I introduced it with if your file is pretty small, .... Commented Sep 9, 2011 at 21:59
2
awk -v n=10 '{sub(/raj/, "ram" n); print; n++}'
1

There are times to use sed, and there are times to not use it.
Because sed doesn't have built-in arithmetic, just use something else.
You can hack sed to do it (without a for-loop), but it is rather pointless and just a messy kludge compared to using something more suited.

With this input data:

printf '%s\n' 'a.raj' 'yyy' 'zzz' 'b.raj c.raj' >file
num=10 # start with this value

Here is a perl method, which increments each and every occurrence of raj (not just once per matched line)

perl -pe 'BEGIN{ $num='$((num-1))' }
          s/raj/ram.($num+=1)/ge' file

output:

a.ram10
yyy
zzz
b.ram11 c.ram12

Here is another perl version, which increments raj only once per matched line (ie. multiple matches on the same line have the same numeric suffix).

perl -pe 'BEGIN{ $num='$num' }
          if(/raj/){ s/raj/ram.$num/ge; $num+=1 }' file

output:

a.ram10  
yyy  
zzz  
b.ram11 c.ram11  

see: When should I NOT use sed

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .