how to replace a value with that value + constant
That's more a job for perl
(which GNU sed
copied that -i
from by the way):
perl -pi -e 's{\$G\K\d+}{
if ($& >= 1 && $& <= 229) {
$& + 229
} else {
$&
}}ge' file
Note that it would also change G0001
to G230
. If you don't want that, you can change the \d+
to [1-9]\d*
.
With your approach, even if you fixed the quoting, that would rewrite the file 229 times and also not work as you'd wish.
A s/\$G1/\$G230/g
, would change $G12
to $G2302
, and the next s/\$G2/\$G231/g
would then change that to G231302
(which the s/\$G23/\$G252
would change to G2521302
and so on).
Single quotes in bash stop variable expansion so the following is looking for the literal $G$num
to replace with the literal $G$N
sed -i -e 's/$G$num/$G$N/g' file
You want bash expansion to happen so you must use double quotes and escape any special characters manually:
sed -i -e "s/\$G$num/\$G$N/g" file
You can see the difference with the following script:
#!/bin/bash
for num in {1..229}; do
N=$(($num+229))
echo '$G$num $G$N' vs "\$G$num \$G$N"
done
Produces
$G$num $G$N vs $G1 $G230
$G$num $G$N vs $G2 $G231
$G$num $G$N vs $G3 $G232
...
$G$num $G$N vs $G228 $G457
$G$num $G$N vs $G229 $G458
sed
solution. Maybe it too tricky and unoptimal, but it works. As an experiment :).
It do all replacements in the one sed
call by executing the one, big command sequence, generated by printf
and paste
usage. I wanted split this command to the multiline for readability, but couldn't - it stops working then. So - the oneliner:
sed -i -r "$(paste -d'/' <(printf 's/%s\\b\n' G{1..229}) <(printf '%s/g\n' G{230..458}))" file.txt
It is converting to the following sed
command:
sed -i -r "s/G1\b/G230/g
s/G2\b/G231/g
s/G3\b/G232/g
s/G4\b/G233/g
...
s/G227\b/G456/g
s/G228\b/G457/g
s/G229\b/G458/g" file.txt
Explanation
sed -i -r "$(
paste -d'/'
- joins left and right parts (which are generated in 3,4 steps) by the slash -/
and the result is this:s/G1\b/G230/g
<(printf 's/%s\\b\n' G{1..229})
- makes left parts of thesed
substitute command. Example:s/G1\b
,s/G2\b
,s/G3\b
, so on.\b
- Matches a word boundary; that is it matches if the character to the left is a “word” character and the character to the right is a “non-word” character, or vice-versa. Information - GNU sed, regular expression extensions.
<(printf '%s/g\n' G{230..458})
- makes right parts of thesed
substitute command. Example:G230/g
,G231/g
,G232/g
, so on.)" file.txt
- input file.
Testing
Input
var G1 = value;
G3 = G1 + G2;
G3 = G1 + G2
G3 = ${G1} + G2
var G2 = value;
var G3 = value;
G224 = G3 + G215;
G124 = G124 + G215;
G124 = G124 + G12;
var G4 = value;
var G5 = value;
var G6 = value;
var G59 = value;
var G60 = value;
var G156 = value;
var G227 = value;
var G228 = value;
var G229 = value;
Output
var G230 = value;
G232 = G230 + G231;
G232 = G230 + G231
G232 = ${G230} + G231
var G231 = value;
var G232 = value;
G453 = G232 + G444;
G353 = G353 + G444;
G353 = G353 + G241;
var G233 = value;
var G234 = value;
var G235 = value;
var G288 = value;
var G289 = value;
var G385 = value;
var G456 = value;
var G457 = value;
var G458 = value;