Add number to number located on line in BASH

I have a sql file that I need to modify so that the row id section is incremented by 3. How can I increase the ID field and keep the rest of the string as it is in BASH? Example:

insert into info.names values (35, 'John', 'C', 2);
insert into info.names values (36, 'Mark', 'C', 1);
insert into info.names values (37, 'Bob', 'C', 5);

      

I need to add 3 to 35, 36 and 37 so that they become 38,39,40. SO the output will be

insert into info.names values (38, 'John', 'C', 2);
insert into info.names values (39, 'Mark', 'C', 1);
insert into info.names values (40, 'Bob', 'C', 5);

      

I would like to do this in BASH.

thank

+3


source to share


3 answers


awk is a better tool for this task

 awk '{tmp=$5 ;sub(/^\(/, "", tmp); tmp+=3; $5="("tmp","; print $0}' file > file.new && mv file.new file

      

To clarify, I'll add comments and use a more verbose format



 awk '{  
       # Capture the 5th field '(35,' into a tmp variable
       tmp=$5                                    
       # remove the leading "(" char
       sub(/^\(/, "", tmp)
       # add 3 to the tmp value (see note below)
       tmp+=3
       # reconstruct the 5th field adding "(" and "," as needed.
       $5="(" tmp ","
       # print the whole line
       print $0
     }' file > file.new && mv file.new file
  #     |                  |-> if no error (`&&`) overwrite the original file 
  #     |                        with the fixed file (not an awk feature)
  #     |-> write output to tmp file                                                            

      

Note that after the operation sub(/^\(/, "", tmp)

, the tmp value is actually 35,

(note the ,

char!). If a variable is set in a numeric context (for example, +=3

), awk only processes the number part of that value and then performs the mathematical operation. That's why you get 38

it instead 35,3

. After that, the string will "return" the missing characters ('and', '.

IHTH

+2


source


Using gnu-awk you can do this:



awk 'BEGIN{ FPAT="[^(]+|\\([0-9]+" } {$2="(" substr($2,2)+3} 1' file.sql
insert into info.names values  (38 , 'John', 'C', 2);
insert into info.names values  (39 , 'Mark', 'C', 1);
insert into info.names values  (40 , 'Bob', 'C', 5);

      

+2


source


Thank. I'm not an awk guru, so there are some things I don't understand. Here's what I did, but it's certainly much ruthless than all of your answers.

sed -n -r 's/^insert .*\(([0-9]+),.*;/\1/p' Names.sql | while read line; do grep "^insert into info.names values ($line," Names.sql | while read SQLLine; do OLDID=$(echo "$SQLLine" | sed -n -r 's/^insert .*\(([0-9]+),.*;/\1/p'); NEWID=$(expr 2 + $OLDID); sed -n -r "s/(insert into info.names values \()[0-9]+(, .*)/\1$NEWID\2/p" <(echo "$SQLLine"); done; done

      

Thanks guys,

0


source







All Articles