
Eingabedatei
CARD SG CLASS ATT
11 0 DAS YES
CARD SG CLASS ATT
12 0 ECT YES
CARD SG CLASS ATT
13 0 VAS YES
1 DAS NO
CARD SG CLASS ATT
14 0 SAT YES
CARD SG CLASS ATT
15 0 CDT YES
1 VEG YES
2 GAT NO
Erwartete Ausgabe:
CARD SG CLASS ATT
11 0 DAS YES
12 0 ECT YES
13 0 VAS YES
13 1 DAS NO
14 0 SAT YES
15 0 CDT YES
15 1 VEG YES
15 2 GAT NO
Was habe ich getan:
awk ' /YES|NO/{VAL=$1};/ATT/{Print "CARD" "SG" "CLASS" "ATT" };/YES|NO/{ print VAL, $2, $3, $4} ' SCGR.txt | column -t
11 0 DAS YES
12 0 ECT YES
13 0 VAS YES
1 DAS NO
14 0 SAT YES
15 0 CDT YES
1 VEG YES
2 GAT NO
Bitte helft mir
Antwort1
Versuchen Sie Folgendes (vorausgesetzt, alle Kopfzeilen sind exakt gleich):
awk ' NR==1{header=$0; count=NF; print; next}
($0~header) {next}
(NF==count) {col1=$1}
(NF<count) {printf("%s",col1)}
1 ' infile | column -t
Antwort2
Debuggen Ihres One Ligners – Mehrere kleinere Probleme:
Print
--print
/ATT/{Print "CARD" "SG" "CLASS" "ATT" }
--/ATT/{print}
oder/ATT/;
/YES|NO/{VAL=$1}
wird auch in den 3 Feldern Datensätze ausgelöst, wodurch der zuvor gespeicherte Wert gelöscht wird. (Ändern Sie die Reihenfolge oder$4 ~ /YES|NO/
)
Eine Variante:
awk 'NF==4{v=$1;print} NF==3{print v,$0}'
Entfernen zusätzlicher Überschriften und Einrückungen:
awk '/^CARD/ && NR>1 { next }
NF==4 { v=$1;print }
NF==3 { print v,$0 }'
Antwort3
Wenn uns die Spaltenausrichtung egal ist und wir nur normalisierte, durch Leerzeichen getrennte Daten wünschen, lautet das grundlegende Muster:
awk -F' +' '{ $1 = ($1 ~ /^$/ ? prev : $1); prev = $1; print }'
Wenn wir einen benutzerdefinierten Feldtrenner einrichten, der nicht dem Standardabstand entspricht, erreichen wir eine echte Trennung der Felder. Wenn der Datensatz mit einer Übereinstimmung für den Trenner beginnt, wird ein leeres Feld abgegrenzt.
Standardmäßig trennt Awk nicht, sondern tokenisiert: Es extrahiert aus jedem Datensatz Token, die Sequenzen aus einem oder mehreren Nicht-Leerzeichen/Nicht-Zeilenumbruchzeichen sind. Das bedeutet, dass führende und nachfolgende Leerzeichen/Zeilenumbrüche ignoriert werden. Wenn also eine Spalte 1 fehlt, wird der Wert in Spalte 2 zu Spalte 1.
Mit unserem / +/
Trennzeichen-Regex erhalten wir echtes Trennverhalten. Ein Datensatz mit führenden und nachfolgenden Leerzeichen wie 1 2 3 4
wird als behandelt <SEP>1<SEP>2<SEP>3<SEP>4<SEP>
. Somit gibt es sechs Felder: ""
, "1"
, ..., "4"
, ""
. Es gibt ein Feld vor dem ersten <SEP>
und nach dem letzten.
Übrigens, wenn im ersten Datensatz möglicherweise ein Feld fehlt, brauchen wir offensichtlich einen Standardwert für prev
. Außerdem möchten wir nicht, dass die Logik auf Überschriften angewendet wird. Ersetzen wir außerdem den ternären Operator durch ein if
: Also:
awk 'BEGIN { FS = " +"; prev = 0 }
NR == 1
NR > 1 { if ($1 == "") $1 = prev
print
prev = $1 }'
FOO BAR BAZ
FOO BAR BAZ
2 3 4
0 2 3 4
1 2 3 4
1 2 3 4
2 3 4
1 2 3 4
Antwort4
Nur für die BildungsedEntscheidung
sed '
1b #output 1st line (header)
$!N #add next line to operate 2 lines altogether
s/\(.*\)\n\(CARD.*\)/\2\n\1/ #move line with CARD to first place
/^CARD/D #delete line with CARD and go to start
s/^\(\([0-9]*\s*\).*\n\)\s\s*/\1\2/
#repeat 1st field of 1st line if empty in 2nd
/\n/{P;D} #print&remove 1st line, go to start
'