2012-12-11 15 views
6

Ich möchte eine Zahl, die in wissenschaftlicher Notation in einem Fließkomma-Dezimal gespeichert ist, konvertieren, so dass ich dann einige Vergleiche zu den Daten durchführen kann. Dies wird in einem Bash-Skript getan - hier ist ein kleiner Ausschnitt aus dem Code:wissenschaftliche Notation in Dezimal konvertieren in Bash

while read track_id landfall_num gate_id pres_inter 
do 
    if [[ $landfall_num == 0001 ]] 
    then 
    start_flag = true 
    echo DING DING $start_flag 
    if [[ $pres_inter < 97000 ]] 
    then 
     echo Strong Storm From North $track_id, $gate_id, $pres_inter 
    fi 
    fi 
done < $file 

Mein Problem ist, dass mein < Operand im Grunde alle der Druckwerte ist die Auswahl, die in der wissenschaftlichen Schreibweise gespeichert ist, wenn ich Verwenden Sie <, und keine, wenn ich > verwenden. Ich schaue auf atmosphärische Druckmessungen in Pascal statt Millibar. Hier

Beispielausgabe:

Strong Storm From North 0039988 0017 1.0074E+05 

Strong Storm From North 0037481 0018 9.9831E+04 

Keines dieser Stürme sollten die Auswahlkriterien treffen!

+0

Warum nicht einfach einen Perl-Einzeiler verwenden? –

Antwort

1

Für numerische Vergleiche, müssen Sie verwenden:

  • -eq statt ==
  • -ne statt !=
  • -lt statt <
  • -le statt <=
  • -gt statt >
  • -ge statt >=

Und einige Syntax-Probleme zu beheben:

while read track_id landfall_num gate_id pres_inter 
do 
    landfall_num=$(printf "%f", "$landfall_num") 
    if [[ "$landfall_num" -eq 1 ]] 
    then 
    start_flag="true" 
    echo "DING DING $start_flag" 
    if [[ "$pres_inter" -lt 97000 ]] 
    then 
     echo "Strong Storm From North $track_id, $gate_id, $pres_inter" 
    fi 
    fi 
done < "$file" 

Aktualisiert:

Dies ist, wie man eine wissenschaftliche Notation Zahl in eine ganze Zahl konvertieren:

printf "%.0f\n", 1.0062E+05 

zum Beispiel druckt:

100620 

Und so:

landfall_num=$(printf "%f", "$landfall_num") 

wird landfall_num aus wissenschaftlicher Notation in eine normale Dezimalzahl konvertieren.

+0

danke. Ich bin nur neugierig - ich habe letzte Woche einen Shell-Programmierkurs absolviert und sie haben nicht über alle Anführungszeichen gesprochen. Warum halten Sie diese Syntax für besser? Vielen Dank! – kimmyjo221

+0

Außerdem erhalte ich den folgenden Fehler: Zeile 28: [[: 1.0062E + 05: Syntaxfehler: ungültiger arithmetischer Operator (Fehler Token ist ". 0062E + 05") – kimmyjo221

+0

Es ist fast immer besser, Variablen in doppelte Anführungszeichen zu umschließen Eliminieren Sie Fälle wie leere Zeichenfolgen oder Zeichenfolgen, die Zeilenumbrüche enthalten. –

6

Als erstes kann bash arithmetische Operationen mit Gleitkommaarithmetik nicht ausführen. Zweitens kennt Bash keine wissenschaftliche Notation (selbst für ganze Zahlen).

Das erste, was Sie versuchen können, wenn Sie sich absolut positiv sicher sind, dass Sie alle Ihre Zahlen ganze Zahlen sind: wandeln sie in Dezimalschreibweise: printf wird gerne das für Sie tun:

printf -v pres_inter "%.f" "$pres_inter" 

(%.f Runden zum nächsten ganze Zahl).

dann bash Arithmetik:

if ((pres_inter < 97000)); then .... 

Diese Lösung ist wunderbar und verwendet keine externe Befehle oder jegliche Subshells: Geschwindigkeit und Effizienz!

Nun, wenn Sie mit nicht ganzen Zahlen zu tun sollten Sie besser bc verwenden, um die Arithmetik zu tun: aber da bc verzögert und befasst sich nicht gut mit der wissenschaftlichen Schreibweise, müssen Sie Ihre Zahlen zu Dezimalnotation konvertieren sowieso . So etwas wie das folgende tun sollten:

printf -v pres_inter "%f" "$pres_inter" 
if (($(bc -l <<< "$pres_inter<97000"))); then ... 

Natürlich ist dies langsamer ist, da Sie eine bc sind gabeln. Wenn Sie mit Ganzzahlen zufrieden sind, bleiben Sie einfach bei der ersten Möglichkeit, die ich Ihnen gegeben habe.

Fertig!

Verwandte Themen