Verwenden Sie das Leerzeichen als Trennzeichen mit dem Befehl cut

328

Ich möchte Leerzeichen als Begrenzer für den cutBefehl verwenden.

Welche Syntax kann ich dafür verwenden?

Jaelebi
quelle
42
unwahr, die Manpage für den Schnitt erklärt dies nicht und ist im Allgemeinen nicht informativ
UncleZeiv
2
Auch "Info Cut" ist in diesem Fall keine Verbesserung.
Cardiff Space Man
3
@ mklement0 Wenn ich mich recht erinnere, habe ich auf einen Kommentar geantwortet, der inzwischen gelöscht wurde, und diese Frage als auf der Manpage beantwortet abgetan, was meiner Meinung nach "unwahr" war, unabhängig davon, ob es einen guten Grund dafür gibt oder nicht - jetzt, obwohl ich zugebe, dass es einen guten Grund für diesen Mangel an Informationen geben könnte, denke ich immer noch, dass Dokumentation ohne gängige Verwendungsbeispiele oft zumindest irritierend ist, wenn sie nicht völlig nutzlos ist
OnkelZeiv
3
@UncleZeiv Verstanden; Danke fürs klarstellen; Angesichts des Interesses an dieser Frage kann man davon ausgehen, dass die manSeite nicht ausreicht. Werfen wir einen Blick darauf: " -d delimVerwenden Sie delimals Feldtrennzeichen anstelle des Tabulatorzeichens." (BSD cut, aber die GNU-Version und die POSIX-Spezifikation geben fast dasselbe an). Die Verwendung einer Shell zum Aufrufen cut- der typische Fall - erfordert daher, dass Sie wissen, wie ein Leerzeichen im Allgemeinen als Argument mithilfe der Shell-Syntax übergeben wird , was wohl nicht die cutAufgabe der Manpage ist. Beispiele aus der Praxis helfen jedoch immer, und auf der GNU- Manpage fehlen sie.
mklement0
4
Obwohl die ausgewählte Antwort technisch korrekt ist, sollten Sie die aktuellere und umfassendere Antwort von @ mklement0 als kanonische Antwort auswählen, damit sie nach oben filtert.
David LeBauer

Antworten:

367
cut -d ' ' -f 2

Dabei ist 2 die Feldnummer des durch Leerzeichen getrennten Felds, das Sie möchten.

RichieHindle
quelle
2
Können Sie cut anweisen, eine beliebige Nummer eines bestimmten Zeichens als Trennzeichen zu verwenden, wie in RegEx? zB eine beliebige Anzahl von Leerzeichen, zB \ s +
Amphibient
3
@foampile Nein, ich glaube nicht, dass du kannst.
Jonathan Hartley
6
Sie können keine regulären Ausdrücke verwenden cut, aber Sie können damit cutsversuchen, alle cutEinschränkungen zu "beheben" : github.com/arielf/cuts
arielf
Können Sie jedes dritte durch Leerzeichen getrennte Feld erhalten? wie cut -d ' ' -f 3,6,9,12,15,18ohne jede nummer angeben zu müssen?
Monocito
168

Wenn Sie Leerzeichen als Trennzeichen verwenden, möchten Sie normalerweise mehrere Leerzeichen als ein Leerzeichen behandeln, da Sie die Ausgabe eines Befehls analysieren, bei dem einige Spalten an Leerzeichen ausgerichtet werden. (und die Google-Suche danach führte mich hierher)

In diesem Fall reicht ein einzelner cutBefehl nicht aus, und Sie müssen Folgendes verwenden:

tr -s ' ' | cut -d ' ' -f 2

Oder

awk '{print $2}'
BeniBela
quelle
2
Vielen Dank für die Verwendung von awk-Beispielen, genau das, was ich brauchte.
Spazm
44

Ergänzung der bestehenden, hilfreichen Antworten; Tipp an den QZ-Support für die Ermutigung, eine separate Antwort zu veröffentlichen:

Hier kommen zwei unterschiedliche Mechanismen ins Spiel:

  • (a) ob cut selbst das an die -dOption übergebene Trennzeichen (in diesem Fall Leerzeichen) ein separates Argument sein muss oder ob es akzeptabel ist, es direkt an dieses anzuhängen-d .

  • (b) wie die Shell im Allgemeinen Argumente analysiert, bevor sie an den aufgerufenen Befehl übergeben werden.

(a) wird durch ein Zitat aus den POSIX-Richtlinien für Versorgungsunternehmen beantwortet (Schwerpunkt Mine)

Wenn die Zusammenfassung eines Standard - Dienstprogramm zeigt eine Option mit einem obligatorischen Option-Argumente [...] eine konforme Anwendung verwenden soll getrennte Argumente für diese Option und das Option-Argument . Eine konforme Implementierung muss es Anwendungen jedoch auch ermöglichen, die Option und das Optionsargument in derselben Argumentzeichenfolge ohne dazwischenliegende Zeichen anzugeben .

Mit anderen Worten: In diesem Fall , weil -d‚s - Option-Argument ist zwingend erforderlich , können Sie wählen , ob das Trennzeichen festlegen , wie :

  • (s) Entweder: ein separates Argument
  • (d) OR: als Wert direkt befestigt an-d .

Sobald Sie (s) oder (d) ausgewählt haben, ist es das String-Literal-Parsing der Shell - (b) -, das zählt:

  • Bei Ansatz (en) sind alle folgenden Formen gleichwertig:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Mit Ansatz (d) sind alle folgenden Formen gleichwertig:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Die Äquivalenz wird durch die Schale erklärt String-Literal-Verarbeitung :

Alle oben genannten Lösungen führen zu genau der gleichen Zeichenfolge (in jeder Gruppe), wenn cutsie angezeigt werden :

  • (s) : cutsieht -dals eigenes Argument ein separates Argument, das ein Leerzeichen enthält - ohne Anführungszeichen oder \Präfix!.

  • (d) : cutsieht -d plus ein Leerzeichen - ohne Anführungszeichen oder \Präfix! - als Teil des gleichen Arguments.

Der Grund, warum die Formen in den jeweiligen Gruppen letztendlich identisch sind, ist zweifach, basierend darauf, wie die Shell String-Literale analysiert :

  • Die Schale ermöglicht Literal spezifiziert werden wie durch einen Mechanismus genannt zitieren , die annehmen kann mehrere Formen :
    • Zeichenfolgen in einfachen Anführungszeichen : Der Inhalt '...'wird wörtlich genommen und bildet ein einzelnes Argument
    • Zeichenfolgen in doppelten Anführungszeichen : Der Inhalt im Inneren "..."bildet ebenfalls ein einzelnes Argument, unterliegt jedoch der Interpolation (erweitert Variablenreferenzen wie $varBefehlssubstitutionen ( $(...)oder `...`) oder arithmetische Erweiterungen ( $(( ... ))).
    • \-Zitieren einzelner Zeichen : Ein \vorangestelltes einzelnes Zeichen bewirkt, dass dieses Zeichen als Literal interpretiert wird.
  • Zitiert durch ergänzt Zitat Entfernung , was bedeutet , dass , sobald die Schale eine Befehlszeile analysiert hat, es entfernt die Anführungszeichen aus den Argumenten (umschließenden '...'oder "..."oder \Instanzen) - also der Befehl Wesen aufgerufen nie die Anführungszeichen sieht .
mklement0
quelle
36

Du kannst auch sagen:

cut -d\  -f 2

Beachten Sie, dass nach dem Backslash zwei Leerzeichen stehen.

Chas. Owens
quelle
30
Die Person, die weiß, dass '\' dem nächsten Charakter entgeht, würde sehr vorsichtig sein, um zu notieren, was als nächstes kam. Die Verwendung von '\', um Leerzeichen wie diesem zu entkommen, ist eine sehr verbreitete Redewendung.
Jonathan Hartley
3
@ Jonathan Hartley gewöhnlich sind die meisten Codes tatsächlich unlesbar :)
Luca Borrione
1
Aus Linux / Unix-Sicht \ war mein erster Versuch und es hat funktioniert. Ich stimme zu, dass es im Vergleich zu weniger offensichtlich ist ' ', aber ich bin sicher, dass viele froh sind, es hier als Bestätigung des Verhaltens zu lesen. Zum besseren Verständnis lesen Sie bitte den Kommentar von @ mklement0 unten.
Tresf
@ JonathanHartley Korrektur: "Die egoistische Person, die weiß, dass '\' dem nächsten Charakter entgeht und davon ausgeht , dass alle anderen das auch wissen". Für persönliche Projekte gilt dies nicht, aber in einer Teamumgebung ist diese Annahme sehr gefährlich (und möglicherweise kostspielig).
Eduard Nicodei
1
@ EduardNicodei Oh, ich stimme zu. Wir sprachen über Leser des Codes ("wer bemerkt ...?"), Nicht über Autoren. In einigen Teams ist es jedoch auch in Ordnung, ein bestimmtes Maß an Kompetenz anzunehmen. Kommt auf die Umwelt an.
Jonathan Hartley
5

Ich habe gerade entdeckt, dass Sie auch verwenden können "-d ":

cut "-d "

Prüfung

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am
fedorqui 'SO hör auf zu schaden'
quelle
1
In der Tat - oder '-d '.
mklement0
3
Beachten Sie, dass aus cut‚Sicht aller folgenden ist identisch: "-d ", '-d ', -d" ", -d' ', und -d\<space>: alle Formen direkt append die Option Argument (ein Raum) die Option ( -d) und das Ergebnis in der exakt gleichen Saite durch die Zeit , cutsie sieht: ein einzige Argument mit d gefolgt von einem Leerzeichen, nachdem die Shell das Entfernen von
Anführungszeichen
1
Die Antwort von @ mklement0 sollte die Antwort sein. Es ist das umfassendste auf dieser Seite (obwohl es ein Kommentar ist).
Tresf
@QZSupport: Ich schätze das Gefühl und die Ermutigung - es hat mich inspiriert, meine eigene Antwort mit zusätzlichen Hintergrundinformationen zu veröffentlichen.
mklement0
1
Lol faszinierende Entdeckung!
Harry
4

Sie können es mit cut nicht einfach machen, wenn die Daten beispielsweise mehrere Leerzeichen haben. Ich habe es nützlich gefunden, die Eingabe zu normalisieren, um die Verarbeitung zu vereinfachen. Ein Trick besteht darin, sed zur Normalisierung wie folgt zu verwenden.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar
Anssi
quelle
3

scut , ein schnittähnliches Dienstprogramm (intelligenter, aber langsamer, das ich erstellt habe), das jeden Perl-Regex als Breaking Token verwenden kann. Das Brechen in Leerzeichen ist die Standardeinstellung, Sie können jedoch auch in Regexen mit mehreren Zeichen, alternativen Regexen usw. brechen.

scut -f='6 2 8 7' < input.file  > output.file

Der obige Befehl würde also Spalten im Leerzeichen aufbrechen und die (0-basierten) Spalten 6 2 8 7 in dieser Reihenfolge extrahieren.

Harry Mangalam
quelle
0

Ich habe eine Antwort (ich gebe eine etwas verwirrende Antwort zu), die sedreguläre Ausdrücke und Erfassungsgruppen beinhaltet:

  • \S* - erstes Wort
  • \s* - Trennzeichen
  • (\S*) - zweites Wort - erfasst
  • .* - Rest der Linie

Als sedAusdruck muss die Erfassungsgruppe maskiert werden, dh \(und\) .

Das \1gibt eine Kopie der erfassten Gruppe zurück, dh das zweite Wort.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Wenn Sie sich diese Antwort ansehen, ist sie etwas verwirrend, und Sie denken vielleicht, warum sich die Mühe machen? Nun, ich hoffe, dass einige "Aha!" und wird dieses Muster verwenden, um einige komplexe Textextraktionsprobleme mit einem einzigen sedAusdruck zu lösen .

Stephen Quan
quelle