Ich versuche, ein bestimmtes (viertes) Feld aus dem spaltenbasierten, durch Leerzeichen angepassten Textstrom zu extrahieren. Ich versuche, den Befehl cut
folgendermaßen zu verwenden:
cat text.txt | cut -d " " -f 4
Leider behandelt cut
nicht mehrere Leerzeichen als ein Trennzeichen. Ich hätte durch awk pfeifen können
awk '{ printf $4; }'
oder sed
sed -E "s/[[:space:]]+/ /g"
um die Leerzeichen zu reduzieren, aber ich würde gerne wissen, ob es eine Möglichkeit gibt, mit cut
und mehreren Begrenzern nativ umzugehen?
Versuchen:
tr -s ' ' <text.txt | cut -d ' ' -f4
Auf der Manpage tr
:
- s, --squeeze-repeats ersetzen jede Eingabesequenz eines wiederholten Zeichens , das in SET1 aufgeführt ist, durch ein einzelnes Vorkommen dieses Zeichens
Wie Sie in Ihrer Frage kommentieren, ist awk
wirklich der richtige Weg. Die Verwendung von cut
ist zusammen mit tr -s
Möglich, um Leerzeichen zu quetschen, wie Kevs Antwort zeigt.
Lassen Sie mich jedoch alle möglichen Kombinationen für zukünftige Leser durchgehen. Erläuterungen finden Sie im Abschnitt Test.
tr -s ' ' < file | cut -d' ' -f4
awk '{print $4}' file
while read -r _ _ _ myfield _
do
echo "forth field: $myfield"
done < file
sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file
Testen wir anhand dieser Datei die folgenden Befehle:
$ cat a
this is line 1 more text
this is line 2 more text
this is line 3 more text
this is line 4 more text
$ cut -d' ' -f4 a
is
# it does not show what we want!
$ tr -s ' ' < a | cut -d' ' -f4
1
2 # this makes it!
3
4
$
$ awk '{print $4}' a
1
2
3
4
Dadurch werden die Felder nacheinander gelesen. Mit _
Geben wir an, dass dies eine Wegwerfvariable als "Junk-Variable" ist, um diese Felder zu ignorieren. Auf diese Weise speichern wir $myfield
Als viertes Feld in der Datei, unabhängig von den Leerzeichen dazwischen.
$ while read -r _ _ _ a _; do echo "4th field: $a"; done < a
4th field: 1
4th field: 2
4th field: 3
4th field: 4
Dies fängt drei Gruppen von Leerzeichen und keine Leerzeichen mit ([^ ]*[ ]*){3}
. Dann fängt es alles ein, was kommt, bis ein Leerzeichen als viertes Feld, das es schließlich mit \1
Druckt.
$ sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' a
1
2
3
4
Nachdem ich von den zu vielen Einschränkungen von cut
enttäuscht war, schrieb ich meine eigene Ersetzung, die ich cuts
nannte für "Schnitt auf Steroiden".
cuts bietet die wahrscheinlich minimalistischste Lösung für dieses und viele andere damit verbundene Probleme beim Ausschneiden/Einfügen.
Eines von vielen Beispielen, die sich mit dieser speziellen Frage befassen:
$ cat text.txt
0 1 2 3
0 1 2 3 4
$ cuts 2 text.txt
2
2
cuts
unterstützt:
paste
erforderlich)und vieles mehr. Keines davon wird von Standard cut
bereitgestellt.
Siehe auch: https://stackoverflow.com/a/24543231/1296044
Quelle und Dokumentation (freie Software): http: //arielf.github.io/cuts/
Dieser Perl-Einzeiler zeigt, wie eng Perl mit awk verwandt ist:
Perl -lane 'print $F[3]' text.txt
Das Autosplit-Array @F
Beginnt jedoch mit dem Index $F[0]
, Während awk-Felder mit $1
Beginnen.
Mit den mir bekannten Versionen von cut
ist dies nicht möglich. cut
ist hauptsächlich zum Parsen von Dateien nützlich, bei denen das Trennzeichen kein Leerzeichen ist (z. B. /etc/passwd
) und die eine feste Anzahl von Feldern haben. Zwei Trennzeichen hintereinander bedeuten ein leeres Feld, und das gilt auch für Leerzeichen.