
Ich habe die folgende Datei, in der die ersten beiden Zeilen wie eine einzelne Spalte (also eine fortlaufende Zeichenfolge) dargestellt sind. Ich möchte sie in Spalten aufteilen und das Zeichen „*“ durch eine Zahl „x“ ersetzen, die die wissenschaftliche Notation und das Spaltenformat als vierte und fünfte Zeile angibt.
0.001000000*********************************************
0.061059059-3524.927327218-3524.938421865***************
0.121118118 -887.564833130 -887.569649256-6250.350946527
0.181177177 -387.169559377 -387.173137963-2743.981985633
0.241236236 -223.812193853 -223.815321341-1504.799155086
0.301295295 -134.073058536 -134.075910507 -924.916305653
0.361354354 -76.668692929 -76.671412688 -612.480371134
Beachten Sie, dass die Zeilen 1, 2 und 3 dasselbe Problem haben, nämlich 2 aufeinanderfolgende Spalten, als ob es sich um eine einzelne Spalte handeln würde (ich möchte ein Leerzeichen zwischen ihnen einfügen). Ich möchte auch eine komplexe Operation wie sqrt((sqrt($2 ^ 2 + $4 ^ 2) + $2) / 2) zwischen den Spalten ausführen.
Erwartete Ergebnisse:
0.001000000 -3524.927327218 -3524.938421865 -6250.350946527
0.061059059 -3524.927327218 -3524.938421865 -6250.350946527
0.121118118 -887.564833130 -887.569649256 -6250.350946527
0.181177177 -387.169559377 -387.173137963 -2743.981985633
0.241236236 -223.812193853 -223.815321341 -1504.799155086
0.301295295 -134.073058536 -134.075910507 -924.916305653
0.361354354 -76.668692929 -76.671412688 -612.480371134
Ich würde gerne wissen, ob es eine Lösung für mein Problem gibt.
Antwort1
Mir scheint, Sie haben zwei sehr unterschiedliche Probleme:
- Unvollständige Zeilen, die Sie ausfüllen müssen
- Zahlen, die ohne Trennzeichen angehängt werden
Obwohl dies wahrscheinlich mit einem einzigen Awk-Aufruf machbar ist, würde ich der Einfachheit halber für jeden Task einen Aufruf verwenden.
Aufgrund Ihrer Beispiele für Ein- und Ausgaben gehe ich davon aus, dass Ihre Zahlen immer 9 Dezimalstellen haben.
Umgang mit dem Problem „Kein Trennzeichen“
awk '{
while ($0 ~ /[0-9]+\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][^ ]/) {
$0=gensub(/([0-9]+\.[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9])([^ ])/, "\\1 \\2", $0)
}
print
}' input.txt > first_step.txt
Hinweis: Wenn Ihre gawk
Version >= 4.0 ist, können Sie [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]
durch ersetzen [0-9]{9}
, was Folgendes ergibt:
awk '{
while ($0 ~ /[0-9]+\.[0-9]{9}[^ ]/) {
$0=gensub(/([0-9]+\.[0-9]{9})([^ ])/, "\\1 \\2", $0)
}
print
}' input.txt > first_step.txt
(Irgendwie leichter zu lesen, oder?) Damit sieht es dann first_step.txt
so aus:
0.001000000 *********************************************
0.061059059 -3524.927327218 -3524.938421865 ***************
0.121118118 -887.564833130 -887.569649256 -6250.350946527
0.181177177 -387.169559377 -387.173137963 -2743.981985633
0.241236236 -223.812193853 -223.815321341 -1504.799155086
0.301295295 -134.073058536 -134.075910507 -924.916305653
0.361354354 -76.668692929 -76.671412688 -612.480371134
Ersetzen von '*' durch Werte aus den folgenden Zeilen
Dies ist auch etwas schwierig zu erreichen. Angenommen, diese '*'-Zeilen kommen nur am Anfang Ihrer Datei vor. Wir werden zunächst dafür sorgen, dass jede Zeile 4 Felder hat:
awk '/\*/ {
a=""
for (i=1; i < 5; i++) {
if (i < NF) a=a" "$i
else a=a" ***************"
}
print a; next
}
{print}' first_step.txt > second_step.txt
Ausgabe insecond_step.txt
0.001000000 *************** *************** ***************
0.061059059 -3524.927327218 -3524.938421865 ***************
0.121118118 -887.564833130 -887.569649256 -6250.350946527
0.181177177 -387.169559377 -387.173137963 -2743.981985633
0.241236236 -223.812193853 -223.815321341 -1504.799155086
0.301295295 -134.073058536 -134.075910507 -924.916305653
0.361354354 -76.668692929 -76.671412688 -612.480371134
Nun zum spaßigen Teil ...
awk 'BEGIN{first_lines=0}
/\*/ {for (i=1; i<NF+1;i++) a[NR, i]=$i; next}
first_lines != 1 {for (i=1; i<NF+1;i++) {a[NR, i]=$i};
for (i=NR-1; i > 0; i--) {
for (j=1; j < NF +1; j++) {
if (a[i, j] ~ /^\**$/) a[i, j] = a[i+1, j]
}
}
for (i=1; i < NR+1; i++) {
for (j=1; j < NF +1; j++) {
printf("%16s", a[i, j])
}
printf("\n")
}
first_lines = 1
next
}
{for (i=1;i<NF+1; i++) printf("%16s", $i)
printf("\n")
}' second_step.txt > output.txt
Ausgabe:
0.001000000 -3524.927327218 -3524.938421865 -6250.350946527
0.061059059 -3524.927327218 -3524.938421865 -6250.350946527
0.121118118 -887.564833130 -887.569649256 -6250.350946527
0.181177177 -387.169559377 -387.173137963 -2743.981985633
0.241236236 -223.812193853 -223.815321341 -1504.799155086
0.301295295 -134.073058536 -134.075910507 -924.916305653
0.361354354 -76.668692929 -76.671412688 -612.480371134