Wie verwende ich 'awk', damit ich nur ein oder zwei Felder in der Zeile bedingt ändern kann?

  • Ich habe eine durch Tabulatoren getrennte Datei mit 16 Feldern. Kann ich awk verwenden, um eins oder Felder bedingt zu ändern und die gesamte Zeile als Ausgabe zu drucken? abhängig vom Wert im ersten Feld möchte ich sagen, dass Sie dem Feld 4 usw. eine bestimmte Zahl hinzufügen. Aber als Ausgabe muss ich die gesamte Zeile drucken. Wenn ja, würde ich gerne wissen, wie.

    22 November 2011
    Sam
3 answers
  • Ja, hier ist ein Ansatz:

     awk '$1 == "ALTER" { $5=$5+5 } 1'
     

    Mit der Beispieldatei von etuardu wird dies produziert

     ALTER xx yy zz 15 10
    NOALT aa bb cc 20 20
    ALTER 11 22 33 35 30
     

    So funktioniert es. Es gibt zwei Fälle, die als ungewöhnliche Muster und Aktionen ausgedrückt werden. Im ersten Fall ist das Muster ein Test des ersten Feldes, um zu sehen, ob es gleich "ALTER" ist, und ruft die Aktion auf, die das fünfte Feld ändert, wenn das Muster als wahr ausgewertet wird. Das zweite Muster ist das letzte 1; es ist immer wahr, also wird die implizite print -Aktion ausgeführt.

    Eine Besonderheit bei dieser Lösung: Die in der Eingabe gelesenen Feldtrennzeichen müssen nicht die in der Ausgabe sein. Mit dem einfachen Formular oben werden die Feldtrennzeichen von den Eingaben als Leerzeichen verstanden, während einzelne Leerzeichen in die Ausgabe geschrieben werden. Setzen Sie FS und OFS auf bestimmte Werte, wenn Sie dies nicht wünschen. Allerdings haben nur Zeilen, in denen ein Feld geändert wurde, die neuen Feldtrennzeichen, sodass bei einer Nulloperation wie '$ 1 = $ 1' alle Datensätze neu erstellt werden müssen (dies ist eine bequeme Möglichkeit, Feldtrennzeichen zu ändern, indem nur $1=$1 ).

    22 November 2011
    Michael J. Barber
  • Ja. Dies ist ein Beispiel für die Verwendung (vielleicht nicht das klügste):

     etuardu@subranu:~$ cat sample.txt 
    ALTER xx yy zz 10 10
    NOALT aa bb cc 20 20
    ALTER 11 22 33 30 30
    etuardu@subranu:~$ awk '{ if ($1=="ALTER") print $1,$2,$3,$4,$5+1,$6-1; else print $0 }' sample.txt 
    ALTER xx yy zz 11 9
    NOALT aa bb cc 20 20
    ALTER 11 22 33 31 29
     

    Bitte beziehen Sie sich auf man awk oder einige Online-Tutorial (es gibt viele) für weitere Informationen.

    22 November 2011
    etuardu
  • Wie wäre es damit (Beispieldatei aus @etuardu) -

     awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' input_file | sed '/^$/d'
     
    • Prüfen Sie mit der if-Anweisung die zu ändernde Zeile.
    • Wenn das erwartete Feld gefunden wurde, nehmen Sie die Änderungen vor, z. $ 5 = $ 5 + 1… so weiter und so weiter.
    • Führen Sie eine for-Schleife aus, indem Sie die Schleife basierend auf der Anzahl der Felder wiederholen.
    • Drucken die Felder, die die aktualisierten Felder enthalten würden.
    • Wenn das erwartete Feld nicht gefunden wird, führen Sie die else-Schleife aus.
    • sed entfernt alle vorhandenen leeren Zeilen aufgrund neuer Zeilen erstellt.

    Beispiel:

    [jaypal~/Temp]$ cat text8 NOALT aa bb cc 20 20 ALTER xx yy zz 10 10 ALTER xx yy zz 10 10 NOALT aa bb cc 20 20 ALTER 11 22 33 30 30 [jaypal~/Temp]$ awk '{if($1=="ALTER") {$5=$5+1;print"\n";for (i=1;i<=NF;i++) printf $i" ";} else print "\n"$0}' text8 | sed '/^$/d' NOALT aa bb cc 20 20 ALTER xx yy zz 11 10 ALTER xx yy zz 11 10 NOALT aa bb cc 20 20 ALTER 11 22 33 31 30
    22 November 2011
    jaypal singh