Eine Frage zu awk


9

Ok, da dies eine komplexe Frage ist, werde ich sie klar erklären. Ich habe einen Dateiinhalt wie folgt angezeigt:

$ Cat File1 
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}

Die Ausgabe, die ich will

-Cool MNB +  POP ;
-Cool MNB  + POP ;
-Cool MNB  + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD +POP ;

Zuerst versuche ich, die letzte Spalte aus dem File1herauszunehmen und durch auszudrucken sed 's/[{}//g' File1 > File3

Danach kopiere ich den gesamten Inhalt File1in einen neuenFile4

cp File1 File4

Danach ersetze ich die Daten innerhalb der File4durch die File3Daten (bedeutet die Daten ohne Klammer eine " File1letzte Spalte diese")

awk 'FNR==NR{a[NR]=$1;next}{$5=a[FNR]}1' File3 File4 >>File5 

Die Ausgabe sollte so sein

ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP MNB
ABC Cool Lol POP TBMKF
ABC Cool Lol POP YUKER
ABC Cool Lol POP EFEFVD

Schließlich versuche ich es

awk -F " '{print - $2,$5 +,$4 ";"}‘ File5

Aber das Ergebnis kam nicht so heraus, wie ich es wollte, nur die ähnlichen Daten MNB sind alle unten aufgeführt, andere wurden nicht angezeigt (Datei eine letzte Spalte Daten),


Verwenden Sie gnu awk?
123

Ich bin mir nicht sicher, was du meinst. Aber ich bin nur ein neuer Anfänger, um awk zu berühren. Dies ist die Aufgabe, die ich erledigen muss. Ich versuche mein Bestes, langsam einen Schritt zu einem Schritt zu tun, um dies basierend auf meinem Verständnis von awk zu tun.
heng960407

1
Typ awk --version, was ist das Ergebnis?
123

2
Bitte ändern Sie Ihren Titel in einen spezifischeren Titel für Ihr Problem. Dies erleichtert es anderen, die in Zukunft ähnliche Fragen haben, diese zu finden. Im Moment ist "Eine Frage zu awk" sehr allgemein.
Tom Fenech

Antworten:


16

Ich weiß nicht, warum Sie Dinge links und rechts kopieren. Das Einfache ist

awk '{print "-" $2, substr($5,2,length($5)-2), "+", $4, ";"}' File1

Ich setze das -in den Anfang und das ;am Ende.

Zwischendurch drucken wir

  • $2 weil wir es so wollen wie es ist.
  • eine Teilzeichenfolge von $5, bei der es sich um die Zeichenfolge ohne das erste und das letzte Zeichen handelt. Wir überspringen das erste Zeichen, indem wir an Position 2 beginnen (awk war schon immer seltsam) und lassen das letzte Zeichen weg, indem wir nur einen Teilstring auswählen, der zwei Zeichen kürzer als das Original ist$5
  • das, +weil wir es wollen
  • und dann $4

Ich bin mir jedoch nicht sicher, ob alle diese Zeichenfolgenfunktionen für GNU awk spezifisch sind.


substr(string, 2)aus dem zweiten Zeichen gibt den Teil starten, wie cut -c2-, tail -n +2, sed '2,$'... Was ist daran so seltsam?
Stéphane Chazelas

3
Dieser Befehl ist Standard und würde sogar mit dem Original awkaus den 70er Jahren funktionieren .
Stéphane Chazelas

@ StéphaneChazelas: Ah, ich habe auf dich gewartet :-) Normalerweise beginnen wir bei 0 zu zählen, was bedeutet, dass Index 2 die dritte Position ist, aber hier ist die zweite Position bei Index 2. Vielen Dank für die Klärung der verbleibenden GNU-Frage.
Bananguin

@Bananguin, in der Unix-Shell und den Dienstprogrammen, wie in den wenigen obigen Beispielen gezeigt, beginnen wir bei 1, nicht bei 0. Die bemerkenswertesten Ausnahmen sind die Arrays von ksh und $ {var: offset} (beide von bash kopiert). Alle anderen Shell-Arrays beginnen bei 1. Siehe auch Gibt es einen Grund, warum das erste Element eines Zsh-Arrays mit 1 anstelle von 0 indiziert wird?
Stéphane Chazelas

7

Mit sed

sed '
    s/\S\+\s/-/
    s/\(\S\+\s\)\{2\}{\(\S\+\)}/\2 + \1;/
    ' File1

Und awk Variation

awk -F"[[:blank:]{}]+" '{print "-" $2, $5, "+", $4}' ORS=" ;\n" File1

6

Einfache TXR- Arbeit:

$ txr -c '@(repeat)
@a @b @c @d {@e}
@(do (put-line `-@b @e + @d ;`))
@(end)' -
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {MNB}
ABC Cool Lol POP {TBMKF}
ABC Cool Lol POP {YUKER}
ABC Cool Lol POP {EFEFVD}
[Ctrl-D][Enter]
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool MNB + POP ;
-Cool TBMKF + POP ;
-Cool YUKER + POP ;
-Cool EFEFVD + POP ;

Verwenden des TXR Lisp awk-Makros zum Transliterieren der Awk-Lösung:

 txr -e '(awk (t (prn `-@[f 1] @{[f 4] [1..-1]} + @[f 3] ;`)))'

Felder befinden sich in der fListe, und die Indizierung basiert auf Null.


1
+1 für den lispigen und kratzigsten Look! Diese Sprache muss in pcg (Programmcode Code Golf)
konkurrieren

@Archemar TXR kann beim Golfen nicht sehr gut mithalten, da es spezielle Sprachen gibt, die dafür ausgelegt sind, einzelnen Charakteren Funktionen zuzuweisen, die dann aneinandergereiht werden können, um eine Komposition zu erzielen.
Kaz

@Archemar Geben Sie einen Eintrag ein in: codegolf.stackexchange.com/questions/68712/output-the-next-kana
Kaz

1
@Kaz Gibt es irgendwo ein TXR-Tutorial? Die Manpage scheint ziemlich groß zu sein. Wie funktioniert es im Vergleich zu awk?
bli

1
@bli GNU Awk ist beim Aufteilen von Feldern durch eine große Datei mindestens 30-mal schneller als das TXR awk-Makro, das mehr als 220 Zeilen interpretierten Codes enthält , einschließlich der Gesamtschleife für die Verarbeitung von Eingabequellen in Datensätze und Felder.
Kaz

3

Die Verwendung von awk ist am einfachsten, wenn die $1,$2,...Felder bereits genau die Zeichenfolgen enthalten, mit denen Sie arbeiten möchten. Das Feldtrennzeichen wird als regulärer Ausdruck interpretiert, wenn es mehr als ein Zeichen enthält. Wir müssen keine Such- und Ersetzungs- oder Teilzeichenfolgenoperationen durchführen, um die {geschweiften Klammern} zu entfernen. Wir zählen sie nur als Teil des Begrenzers.

awk -F'[ {}]+' '{printf("-%s %s + %s ;\n", $2, $5, $4)}'

Wenn Sie printfanstelle von verwenden, printist es auch etwas einfacher zu sehen, wie die Zeichenfolge formatiert wird. Wenn Sie jedoch print "-"$2,$5" + "$4";"anstelle von verwenden möchten printf("-%s %s + %s ;\n", $2, $5, $4), ist dies eine Option.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.