So wiederholen Sie den Spaltenwert, wenn die Zelle in der nächsten Zeile leer ist

So wiederholen Sie den Spaltenwert, wenn die Zelle in der nächsten Zeile leer ist

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 4wird 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 
    '

verwandte Informationen