Formatierung von Dezimal zu Exponential

Formatierung von Dezimal zu Exponential

Ich habe eine Datendatei abc.txt im folgenden Format:

BALT 1
 54.500 -161.070
 3.95863757
 0.01691576
BARM 2
 -9.200 67.120
 4.07529868
 0.01951653
BKSR 3
 43.830 142.520
 4.08919819
 0.00587340

Ich muss es in das folgende Format konvertieren:

BALT 1
 54.5000000 -161.070000
 0.3958637E+01
 0.1691576E-01
BARM 2
 -9.20000000 67.1200000
 0.4075298E+01
 0.1951653E-01
BKSR 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02

Die Gesamtzahl der von den Zahlen in der 2. Zeile belegten Leerzeichen sollte 10 betragen, ohne Minuszeichen (z. B. 54.500 als 54.5000000 und -161.070 als -161.070000). Die Leerzeichen für die 3. und 4. Zeile sollten 13 betragen (z. B. 3.95863757 als 0.3958637E+01). Und BALT oder BARM sind Variablen, es können auch andere Wörter mit vier Zeichen sein.

Danke schön.

Antwort1

Version 3verwenden Sie eine Awk-Datei wie

function tenth(x) {
  u = x ; if ( u < 0 ) u = -x ;
  b=10 ;
  a=b-2 ;
  if ( u >= 10 ) {
  d=int(log(u)/log(10)) ;
  a=b-d-1 ;
  }
  printf "%*.*f",b,a,x ;
}
length($1) == 4 { print ; next  ;}
NF == 1 { d=int(log($1)/log(10)) ;if (d> -1) d++ ; printf " %.7fE%+03d\n",$1/(10^d),d ;}
NF == 2 { printf " " ; tenth($1); printf " " ; tenth($2) ; printf "\n" ;}

Wo

  • lengtht$1) == 4 { print ; next ;} lässt die Zeile unverändert, in der das erste Feld vier Buchstaben enthält (das können aber auch 1234 sein)
  • function tenth(x): Definieren Sie eine Funktion, die die Formatierung anpasst.
  • "%*.*f"Zeichenfolge, die Größe/Genauigkeit der %fKonvertierung anpasst. Das erste * wird durch b ersetzt, das zweite * wird durch a ersetzt.
  • int(log()/log(10))Geben Sie einen Dezimallogarithmus an, der die Darstellung an Ihren spezifischen Bedarf anpasst?

Verwenden Sie es mit

awk -f f.awk input

die als Ergebnis geben

BALT 1
 54.5000000 -161.070000
 0.3958638E+01
 0.1691576E-01
BALT 2
 -9.20000000 67.1200000
 0.4075299E+01
 0.1951653E-01
BALT 3
 43.8300000 142.520000
 0.4089198E+01
 0.5873400E-02
 0.00000000 1.00000000
 -3.14150000 2.71828183

Antwort2

Vielleicht so etwas wie:

awk '
  !/[[:alpha:]]/{
    if (NF == 1)
      $0 = sprintf(" %.7E", $0 * 10)
    else
      $0 = sprintf(" %.8f %.8f", $1, $2)
  }
  {print}' | sed '
    s/\([0-9.]\{10\}\)[0-9]*/\1/g
    s/\([1-9]\)\.\(.*\).E/0.\1\2E/'

Antwort3

Sie können es ohne awk erhalten mit:

while read line; do echo $line; read a; read b; read c;  printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

Allerdings kann die Verwendung von printf auf diese Weise zu Problemen führen, wenn Sie ein Gebietsschema mit Kommas statt Punkten verwenden. In diesem Fall sollten Sie das Problem folgendermaßen beheben können:

while read line; do echo $line; read a; read b; read c; LC_NUMERIC="en_US.UTF-8" printf "%.7f %.7f\n %.7e\n %.7e\n" $a $b $c; done < data.txt

Natürlich sollten Sie es in einem Skript besser mit Wagenrücklauf und Einrückung formatieren.

verwandte Informationen