web-dev-qa-db-de.com

Wie lässt man den Befehl 'cut' dieselben sequenziellen Begrenzer wie einen behandeln?

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?

298
mbaitoff

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 
532
kev

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 | Schnitt

tr -s ' ' < file | cut -d' ' -f4

awk

awk '{print $4}' file

bash

while read -r _ _ _ myfield _
do
   echo "forth field: $myfield"
done < file

sed

sed -r 's/^([^ ]*[ ]*){3}([^ ]*).*/\2/' file

Tests

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

tr | Schnitt

$ 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

$ awk '{print $4}' a
1
2
3
4

bash

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

sed

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
86
fedorqui

kürzeste/freundlichste Lösung

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:

  • automatische Erkennung der häufigsten Feldbegrenzer in Dateien (+ Möglichkeit, Standardeinstellungen zu überschreiben)
  • multi-Char-, Mixed-Char- und Regex-Trennzeichen
  • spalten aus mehreren Dateien mit gemischten Trennzeichen extrahieren
  • offsets vom Zeilenende (mit negativen Zahlen) zusätzlich zum Zeilenanfang
  • automatisches Einfügen von Spalten nebeneinander (kein separates Aufrufen von paste erforderlich)
  • unterstützung für die Feldumordnung
  • eine Konfigurationsdatei, in der Benutzer ihre persönlichen Einstellungen ändern können
  • großer Wert auf Benutzerfreundlichkeit und minimalistisches Tippen

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/

25
arielf

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.

3
Chris Koknat

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.

3
Benoit