
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}'
awk
Beachten Sie auch , dass Sie als Spaltentrennzeichen |
anstelle von Leerzeichen erkennen können , sodass Sie keines sed
von 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 -F
Flag zu verwenden, aber hier sind drei Ansätze.
Sie können die Eingabe- und Ausgabefeldtrennzeichen selbst
awk
im BEGIN-Block zuweisen.awk 'BEGIN {FS = OFS = "|"} {print $1, $8}' logfile
Sie können diese Variablen beim Aufruf
awk
aus der Kommandozeile über das-v
Flag zuweisen.awk -v 'FS=|' -v 'OFS=|' '{print $1, $8}' logfile
oder einfach:
awk -F '|' '{print $1 "|" $8}' logfile
Antwort2
Sie verwenden awk
sowieso:
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 sed
Implementierung gibt, bei der |
es sich um ein spezielleserweitertreguläre Ausdrücke sind in einigen Implementierungen nicht aktiviert ( -E
oder nicht aktiviert), selbst ist in einigen Implementierungen wie GNU etwas Besonderes . Sie sollten also-r
\|
sed
nichtEscape |
, 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 sed
wü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