Wie verwende ich einen Shell-Befehl, um in einer Textdatei nur die erste und die letzte Spalte anzuzeigen?

Wie verwende ich einen Shell-Befehl, um in einer Textdatei nur die erste und die letzte Spalte anzuzeigen?

Ich brauche Hilfe, um herauszufinden, wie ich mit dem sed-Befehl nur die erste und die letzte Spalte in einer Textdatei anzeigen kann. Hier ist, was ich bisher für Spalte 1 habe:

cat logfile | sed 's/\|/ /'|awk '{print $1}'

Mein schwacher Versuch, auch die letzte Spalte anzuzeigen, war:

cat logfile | sed 's/\|/ /'|awk '{print $1}{print $8}'

Dabei werden jedoch die erste und die letzte Spalte in einer Liste zusammengeführt. Gibt es eine Möglichkeit, die erste und die letzte Spalte mit den Befehlen sed und awk klar auszudrucken?

Beispieleingabe:

foo|dog|cat|mouse|lion|ox|tiger|bar

Antwort1

Fast geschafft. Setzen Sie einfach beide Spaltenverweise nebeneinander.

cat logfile | sed 's/|/ /' | awk '{print $1, $8}'

Beachten Sie auch, dass Sie dies hier nicht benötigen cat.

sed 's/|/ /' logfile | awk '{print $1, $8}'

awkBeachten Sie auch , dass Sie als Spaltentrennzeichen |anstelle von Leerzeichen erkennen können , sodass Sie keines sedvon beiden benötigen.

awk -F '|' '{print $1, $8}' logfile

GemäßVorschlägevonKaleb, wenn Sie eine Lösung wünschen, die auch dann noch das letzte Feld ausgibt, wenn es nicht genau acht sind, können Sie verwenden $NF.

awk -F '|' '{print $1, $NF}' logfile

Wenn Sie möchten, dass die |Trennzeichen in der Ausgabe beibehalten werden, können Sie statt eines Leerzeichens die Ausgabefeldtrennzeichen angeben. Leider ist das etwas umständlicher, als einfach das -FFlag zu verwenden, aber hier sind drei Ansätze.

  • Sie können die Eingabe- und Ausgabefeldtrennzeichen selbst awkim BEGIN-Block zuweisen.

    awk 'BEGIN {FS = OFS = "|"} {print $1, $8}' logfile
    
  • Sie können diese Variablen beim Aufruf awkaus der Kommandozeile über das -vFlag zuweisen.

    awk -v 'FS=|' -v 'OFS=|' '{print $1, $8}' logfile
    
  • oder einfach:

    awk -F '|' '{print $1 "|" $8}' logfile
    

Antwort2

Sie verwenden awksowieso:

awk '{ print $1, $NF }' file

Antwort3

Ersetzen Sie einfach vom ersten bis zum letzten |durch ein |(oder ein Leerzeichen, wenn Sie das bevorzugen):

sed 's/|.*|/|/'

Beachten Sie, dass es zwar keine sedImplementierung gibt, bei der |es sich um ein spezielleserweitertreguläre Ausdrücke sind in einigen Implementierungen nicht aktiviert ( -Eoder nicht aktiviert), selbst ist in einigen Implementierungen wie GNU etwas Besonderes . Sie sollten also-r\|sednichtEscape |, wenn es dem |Zeichen entsprechen soll.

Wenn Sie durch Leerzeichen ersetzen und die Eingabe möglicherweise bereits Zeilen mit nur einem enthält |, müssen Sie dies speziell behandeln, da es |.*|auf diese keine Übereinstimmung gibt. Das könnte sein:

sed 's/|\(.*|\)\{0,1\}/ /'

(das heißt, den .*|Teil optional machen) Oder:

sed 's/|.*|/ /;s/|/ /'

oder:

sed 's/\([^|]*\).*|/\1 /'

Wenn Sie das erste und das achte Feld unabhängig von der Anzahl der Felder in der Eingabe möchten, dann heißt es einfach:

cut -d'|' -f1,8


(alle diese würden mit jedem POSIX-kompatiblen Dienstprogramm funktionieren, vorausgesetzt, die Eingabe bildet gültigen Text (insbesondere sedwürden diese im Allgemeinen nicht funktionieren, wenn die Eingabe Bytes oder Bytefolgen enthält, die im aktuellen Gebietsschema keine gültigen Zeichen bilden, wie beispielsweise printf 'unix|St\351phane|Chazelas\n' | sed 's/|.*|/|/'in einem UTF-8-Gebietsschema)).

Antwort4

Es scheint, als würden Sie versuchen, das erste und letzte Textfeld abzurufen, die durch getrennt sind |.

Ich nahm an, dass Ihre Protokolldatei den folgenden Text enthält:

foo|dog|cat|mouse|lion|ox|tiger|bar
bar|dog|cat|mouse|lion|ox|tiger|foo

Und Sie möchten eine Ausgabe wie diese:

foo bar
bar foo

Wenn ja, dann kommt hier der Befehl für Ihre

Durch GNU sed,

sed -r 's~^([^|]*).*\|(.*)$~\1 \2~' file

Beispiel:

$ echo 'foo|dog|cat|mouse|lion|ox|tiger|bar' | sed -r 's~^([^|]*).*\|(.*)$~\1 \2~'
foo bar

verwandte Informationen