0

I have a .txt file containing a column of values, something like:

2453882.157576
2453882.157947
2453882.159972
2453882.160354
2453882.160724

And I want to add a single value to each line in the code, let's say 5. So the output would be:

2453887.157576
2453887.157947
2453887.159972
2453887.160354
2453887.160724

I'm fairly new to bash commands and I am a bit unsure what commands to use. I thought it might be useful to try to iterate through the file and simply add through it:

while read i; do
  shift=$(($i + $5)) 
done <filename.txt > shifted_by_5_filename.txt

but this outputs an error "invalid arithmetic operator". Are there any suggestions on how to accomplish this task?

UPDATE: With some of the suggestions below, I've looked into using awk to try to add floats (rather than interger addition). I've found another question: how to add Integer number and a float number in unix shell script

that has an answer to add two floats:

echo 1.234 2.345 | awk '{print $1 + $2}'

To try to extend this to my problem, I've tried the following:

while read i
do echo $i 5 | awk '{print sprintf("%.9f", ($1+ $2))}'
done < filename.txt > shifted_by_5_filename.txt

The sprintf command is to try to produce an output not in scientific notation. However, as with the suggestions below, this attempt does not add by 5 rather it adds by 2.771413. I'm a bit perplexed by this. Any ideas?

Dax Feliz
  • 12,220
  • 8
  • 30
  • 33

4 Answers4

4

Bash doesn't handle floating point arithmetics. You need an external command, e.g. bc:

sed 's/$/+5/' file.txt | bc

The sed command just adds +5 to the end of each line, it's faster and easier than reading the input line by line by the shell.

choroba
  • 231,213
  • 25
  • 204
  • 289
  • When I run this, it doesn't add 5 to each line but adds about 2.77 instead. Any idea on what this could mean? – Dax Feliz Jun 25 '17 at 22:28
  • @DaxFeliz: Does you input really contain just the numbers? – choroba Jun 25 '17 at 22:31
  • Yes. It's a simple column of numbers. I'm exploring a suggestion with awk, I found here: echo 1.234 2.345 | awk '{print $1 + $2}' https://stackoverflow.com/questions/16355229/how-to-add-integer-number-and-a-float-number-in-unix-shell-script – Dax Feliz Jun 25 '17 at 22:32
1

Bash can only do integer arithmetic. The simplest way is probably to use bc:

while read i; do
   echo $(bc <<< "$i + 5")                                                  
done <filename.txt > shifted_by_5_filename.txt

Alternatively, you could use some general purpose interpreter, e.g. Perl:

perl -ple '$_ += 5' filename.txt > shifted_by_5_filename.txt
Eugene Yarmash
  • 142,882
  • 41
  • 325
  • 378
  • Thank you so much! I've altered the numbers in my original code to reflect an issue with this approach that I've had. When I run this, it doesn't add 5 to each line but adds about 2.77 instead. Any idea on what this could mean? – Dax Feliz Jun 25 '17 at 22:28
  • This works for me with your sample data. Do you use exactly the code above? (e.g. `"$i + 5"` and not `"$i + $5"`) – Eugene Yarmash Jun 25 '17 at 22:55
  • Strange. I've tried $(bc <<< "$i + 5") as you suggested inside the while loop but still get that 2.771413 addition rather than 5. If it helps any, I'm on a Mac OSX. I appreciate your feedback! – Dax Feliz Jun 25 '17 at 22:57
  • Unfortunately, I can't try it on Mac now. Is using Perl an option? :) – Eugene Yarmash Jun 25 '17 at 23:13
1

Arithmetic expansion in bash works only for integers, so for floats you'll need bc, awk, python, perl, ruby, or similar. For example with bc:

while read i; do
   echo "$i + 5" | bc -l
done <filename.txt > shifted_by_5_filename.txt

Or with this simple awk script:

awk '{print $0+5}' filename.txt >shifted_by_5_filename.txt
randomir
  • 17,989
  • 1
  • 40
  • 55
1

I believe that there are two pretty clear issues here. First of all it looks like you are missing a parenthesis when you are performing the addition. Secondly, you do not need a dollar on the number 5.

With a shift variable:

while read i; do
    shift=5
    sum=$(($i+$shift))
    echo $sum
done < input.txt > output.txt

Or if you want to use your constant:

while read i; do
    sum=$(($i+5))
    echo $sum
done < input.txt > output.txt
  • Thank you for the suggestion. Both of these attempts produce the initial error I encounted: "invalid arithmetic operator (error token is ".928989+5")" – Dax Feliz Jun 25 '17 at 22:52