0

I'm trying to replace floating-point numbers like 1.2e + 3 with their integer value 1200. For this I use sed in the following way:

 echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/$(echo \1*10^\2|bc -l)/"

but the pattern parts \1 and \2 doesn't get evaluated in the echo.

Is there a way to solve this problem with sed? Thanks in advance

Mauri
  • 1,185
  • 1
  • 13
  • 21
  • 1
    See [How to get bc to handle numbers in scientific (aka exponential) notation?](https://stackoverflow.com/questions/12882611/how-to-get-bc-to-handle-numbers-in-scientific-aka-exponential-notation) – Wiktor Stribiżew Jan 16 '19 at 11:33

4 Answers4

1

If you are happy with awk command like this can do the work:

echo 1.2e+4|awk '{printf "%d",$0}'
Romeo Ninov
  • 6,538
  • 1
  • 22
  • 31
1

Within the double quotes, \1 and \2 are interpreted as literal 1 and 2. You need to put additional backslashes to escape them. In addition, $(command substitution) in sed replacement seems not to work when combined with back references. If you are using GNU sed, you can instead say something like:

echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/echo \"\\1*10^\\2\"|bc -l/;e"

which yields:

12000.0

If you want to chop off the decimal point, you'll know what to do ;-).

tshiono
  • 21,248
  • 2
  • 14
  • 22
0

It is perhaps better to use perl (or other typed language) to manage the variable types:

echo '"1.2e+04"' | perl -lane 'my $a=$_;$a=~ s/"//g;print sprintf("%.10g",$a);print $a;'

In any case, your sed expression is incorrect, it should be:

echo '"1.2e+04"' | sed "s/\"\([0-9]\+\.[0-9]\+\)e+\([0-9]\+\)\"/$(echo \1*10^\3 + \2*10^$(echo \3 - 1 | bc -l)|bc -l)/"

user7440787
  • 831
  • 7
  • 22
  • how you are getting the value for `\3` in `sed` command, also i believe the output of your `sed` command should be `12000` instead of `1200` . – User123 Jan 16 '19 at 11:30
0

The best way to solve the problem properly is to use an advanced combination of @ tshiono and @ Romeo solutions:

sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

So it is possible to convert all such floats into arbitrary contexts.

for example:

echo '"1.2e+04"' | sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

outputs

"12000"

and

echo 'abc"1.2e+04"def' | sed "s/\(.*\)\([0-9]\+\.[0-9]\+e+[0-9]\+\)\(.*\)/printf '\1'\; echo \2 |awk '{printf \"%d\",\$0}'\;printf '\3'\;/e"

outputs

abc"12000"def
Mauri
  • 1,185
  • 1
  • 13
  • 21