Adding a specified value to a specified column - awk?

Hi everyone!

I sometimes need to do some simple arithmetics, like adding a number to a certain column of a file. So I wrote a small function in the .bashrc file, which looks like this

 shifter()
 {
 COL=$1
 VAL=$2
 FILE=$3

 cp $FILE $FILE.shifted
 awk 'NF==4 {$(( $COL )) = $(( $COL )) + $VAL}' $FILE.shifted
 }

which should add the number stored in VAL, to the column COL from the FILE file.

Please give me a hint how should I make this work. Thank you! (I'm just a newbie in shell programing)

You've got a pretty good grasp for a newbie, but a couple things of note.

Variables do not expand inside single quotes. Never have, never will. They do inside double quotes, but I don't reccomend using double quotes for awk code -- makes it awkward since you need to \-escape so many things.

Awk does not use shell variables, it's its own self-contained language with its own variables. You can get them into awk, but you have to put them there in the first place...

awk does not use $ to mean variable. $ means column in awk. So N=1; print $N would be equivalent to print $1 -- i.e. print the first column.

awk does not edit the file you give to it, it just prints it somewhere else. So you can use it instead of cp here, by sending the altered output into a new file.

Your awk statement prints no lines. The statement '1' outside a code block simply prints every line.

So:

shifter()
 {
        awk 'NF==4 {$COL += VAL } 1' COL=$1 VAL=$2 $3 > "$3.shifted"
 }
1 Like

Hi Corona688!

I've tried your code, and it works if I get rid of the 'NF==4'. Thank you!

Since you never posted your input data, I didn't know what the NF==4 was for.

One more thing: although the script works, it does it with a low precission (meaning, having to many decimals, the script will consider only the first 4, or somethign like this).

What should I include in the script in order to keep the same precission or what flags/options should I send to awk in order to keep the same preccision?

Thank you!

An example

~/r/cu.t cat xx
 10.83000000  12.63500000  32.92017254 6
 12.63500000  10.83000000  32.92017254 6
~/r/cu.t shifter 3 45.11111111 xx 
~/r/cu.t cat xx.shifted 
10.83000000 12.63500000 78.0313 6
12.63500000 10.83000000 78.0313 6

What I would like is to have something like this

~/r/cu.t cat xx.shifted 
 10.83000000  12.63500000  78.03128365 6
 12.63500000  10.83000000  78.03128365 6

awk uses 32-bit floating point numbers, its precision is not infinite. By default it prints to 6 digits, but this can be controlled by the CONVFMT variable. Hopefully this works for your need:

awk 'NF==4 {$COL += VAL } 1' COL=$1 VAL=$2 CONVFMT="%.8f" $3 > "$3.shifted"
1 Like

Thank you once again, Corona688! :slight_smile: