Hello, I am trying to write a bash script which will give me the most negative number. Here is an example input:
Ce 3.7729752124 -4.9505731588 -4.1061257680
Ce -6.9156611391 -0.5991784762 7.3051893138
Ce 7.6489739875 0.3513020731 -4.1428887409
O -2.0367674927 6.4059113030 4.2342869120
O 1.8496529300 6.8212696160 0.4577675608
I used
grep -- "-*"
which returns all lines with negative numbers, what I really need is for it to look and find (in this instance) -6.9156611391. Then add +6.9156611391 to all the numbers in the file ex.
Ce 3.7729752124 -4.9505731588 -4.1061257680
to
Ce 10.6886363515 1.9650879... 2.80953537...
All lines do not necessarily contain number nor do they start with Ce or O,
however all numbers that need changed have the 3 set format (x,y,z coordinates)
was sufficient. The * didn't do what you think it did -- it would've matched any number of dashes in a row.
To get the most negative number:
awk '{ for(N=2; N<=NF; N++) if((!MIN)||($N < MIN)) MIN=$N } END { print MIN }' filename
Expanding on that, this finds the minimum then subtracts from all lines:
awk -v OFS="\t" '
# Run this for all lines in the first given file
NR==FNR { for(N=2; N<=NF; N++) if((!MIN)||($N < MIN)) MIN=$N; next }
# Run this for all lines in any following files
{ for(N=2; N<=NF; N++) $N -= MIN; } 1' inputfile inputfile > outputfile
Yes, the same file is listed twice intentionally. The first time it reads it, it finds the minimum; the second time, it subtracts the minimum and prints.
It gives me this output:
Ce 10.6886 1.96509 2.80954
Ce 0 6.31648 14.2209
Ce 14.5646 7.26696 2.77277
O 4.87889 13.3216 11.1499
O 8.76531 13.7369 7.37343
Keep in mind that this can't write to the same file it's reading from.
Thank you for the replies, it almost works...
In the first reply,
0 needs to comeback as 0.0000000
in the second reply I received two strange parts in the file, one, the line
O 11.4730666365 0.0845493182000006 7.1215466626 with several extra decimal points
Two, a line O 12.69964795 0 12.7680007771 with no z coordinate.
In the third reply the decimal points end at 5 places.
I should add the text file is several thousand lines long so the demo values I gave are not all of it nor the lowest value
awk -v OFS="\t" '
# Run this for all lines in the first given file
NR==FNR { for(N=2; N<=NF; N++) if((!MIN)||($N < MIN)) MIN=$N; next }
# Run this for all lines in any following files
{ for(N=2; N<=NF; N++) $N =sprintf("%.10f", $N-MIN); } 1' inputfile inputfile > outputfile
But awk math is floating point, not infinite precision.