
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%f
Konvertierung 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.