2012-12-11 18 views
6

Mi piacerebbe convertire un numero memorizzato in notazione scientifica in un decimale in virgola mobile, quindi posso quindi eseguire alcuni confronti sui dati. Questo è stato fatto in uno script bash - ecco un piccolo frammento di codice:Converti notazione scientifica in decimale 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 

Il mio problema è che il mio < operando sta selezionando praticamente tutti i valori di pressione, che vengono memorizzati in notazione scientifica, quando ho utilizzare < e nessuno quando uso >. Sto osservando le misurazioni della pressione atmosferica in pascal piuttosto che millibar.

Ecco un esempio di output:

Strong Storm From North 0039988 0017 1.0074E+05 

Strong Storm From North 0037481 0018 9.9831E+04 

Nessuna di queste tempeste dovrebbe essere che soddisfano i criteri di selezione!

+0

Perché non usare solo un rivestimento perl? –

risposta

1

Per i confronti numerici, è necessario utilizzare:

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

E per correggere alcuni problemi di sintassi:

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" 

Aggiornato:

Questo è il modo di convertire un numero notazione scientifica in un numero intero:

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

per esempio, le stampe:

100620 

E così:

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

convertirà landfall_num dalla notazione scientifica in un intero decimale normale.

+0

grazie. Solo curioso: ho appena seguito un corso di programmazione shell la scorsa settimana e non hanno parlato di tutte le virgolette. Perché consideri questa sintassi migliore? Grazie! – kimmyjo221

+0

Inoltre, viene visualizzato il seguente errore: riga 28: [[: 1.0062E + 05: errore di sintassi: operatore aritmetico non valido (token di errore è ".0062E + 05") – kimmyjo221

+0

È quasi sempre meglio racchiudere le variabili tra virgolette doppie eliminare casi d'angolo come stringhe vuote o stringhe che contengono righe nuove. –

6

Per prima cosa, bash non può eseguire l'aritmetica utilizzando l'aritmetica in virgola mobile. Seconda cosa, bash non conosce la notazione scientifica (anche per i numeri interi).

La prima cosa che si può provare, se siete assolutamente positivamente in modo che tutti i numeri sono interi: convertirli in notazione decimale: printf sarà lieto di farlo per voi:

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

(%.f giri dalla più vicina numero intero).

quindi utilizzare l'aritmetica di bash:

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

Questa soluzione è meraviglioso e non usufruisce di comandi esterni o qualsiasi sottoshell: velocità ed efficienza!

Ora, se hai a che fare con i non interi è meglio usare bc per fare l'aritmetica: ma poiché bc è ritardato e non lavora bene con la notazione scientifica, è necessario convertire i numeri in notazione decimale in ogni modo . Quindi qualcosa di simile alla seguente dovrebbe fare:

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

Naturalmente, questo è più lento dato che si sta biforcano un bc. Se sei soddisfatto dei numeri interi, tieni semplicemente la prima possibilità che ho dato.

Fatto!

Problemi correlati