Usa lo spazio come delimitatore con il comando taglia


328

Voglio usare lo spazio come delimitatore con il cutcomando.

Quale sintassi posso usare per questo?


42
falso, la pagina man di cut non spiega questo ed è, in generale, non istruttiva
UncleZeiv

2
Inoltre, "info cut" non è un miglioramento in questo caso.
cardiff space man

3
@ mklement0 se ricordo, stavo rispondendo a un commento che è stato poi cancellato, che stava respingendo questa domanda come risposta nella pagina man, che secondo me era "non vera", indipendentemente dal fatto che ci fosse una buona ragione oppure no - ora, mentre ammetto che potrebbe esserci una buona ragione per questa mancanza di informazioni, continuo a pensare che la documentazione senza esempi di utilizzo comuni sia spesso irritante, quando non del tutto inutile
UncleZeiv

3
@UncleZeiv Capito; grazie per il chiarimento; dato l'interesse per questa domanda, è giusto presumere che la manpagina non sia sufficiente. Diamo un'occhiata: " -d delimUsa delimcome carattere delimitatore di campo invece del carattere di tabulazione". (BSD cut, ma la versione GNU e le specifiche POSIX dichiarano praticamente lo stesso). L'uso di una shell per invocare cut- il caso tipico - richiede quindi di sapere come passare generalmente uno spazio come argomento usando la sintassi della shell , che probabilmente non è il cutlavoro della pagina man. Gli esempi del mondo reale aiutano sempre, tuttavia, e la pagina man GNU li manca.
mklement0

4
anche se la risposta selezionata è tecnicamente corretta, considera di selezionare la risposta più recente e completa di @ mklement0 come risposta canonica in modo che filtra all'inizio.
David LeBauer,

Risposte:


367
cut -d ' ' -f 2

Dove 2 è il numero di campo del campo delimitato da spazi desiderato.


2
puoi dire a cut di usare un numero qualsiasi di un certo carattere come delimitatore, come in RegEx? ad esempio un numero qualsiasi di spazi, ad esempio \ s +
anfibio,

3
@foampile No, non credo che tu possa.
Jonathan Hartley,

6
Non puoi usare regexes cut, ma puoi con cutscui provare a "correggere" tutte le cutlimitazioni: github.com/arielf/cuts
arielf

puoi ottenere ogni terzo campo delimitato da spazi? come cut -d ' ' -f 3,6,9,12,15,18senza dover specificare ogni numero?
Monocito

169

In genere, se si utilizza lo spazio come delimitatore, si desidera trattare più spazi come uno, poiché si analizza l'output di un comando allineando alcune colonne con gli spazi. (e la ricerca su Google per questo mi porta qui)

In questo caso un singolo cutcomando non è sufficiente ed è necessario utilizzare:

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

O

awk '{print $2}'

2
Grazie per il fantastico esempio di utilizzo, proprio quello di cui avevo bisogno.
spazm,

44

Integrare le risposte esistenti e utili; suggerimento per il supporto QZ per avermi incoraggiato a pubblicare una risposta separata:

Qui entrano in gioco due meccanismi distinti :

  • (a) se cut si richiede il delimitatore (spazio, in questo caso) passato alla -dpossibilità di essere un argomento separato o se è accettabile aggiungerlo direttamente a -d.

  • (b) come la shell generalmente analizza gli argomenti prima di passarli al comando che viene invocato.

(a) viene fornita una risposta dalle linee guida POSIX per le utility (sottolineatura mia)

Se la SINOSSI di un'utilità standard mostra un'opzione con un argomento opzione [...] obbligatorio, un'applicazione conforme deve usare argomenti separati per quell'opzione e il suo argomento opzione . Tuttavia , un'implementazione conforme deve anche consentire alle applicazioni di specificare l'opzione e l'opzione-argomento nella stessa stringa di argomenti senza caratteri intermedi .

In altre parole: in questo caso, poiché -dl'opzione-argomento è obbligatoria , puoi scegliere se specificare il delimitatore come :

  • (s) OGNI: un argomento separato
  • (d) OPPURE: come valore direttamente collegato a-d .

Dopo aver scelto (s) o (d), è l' analisi stringa-letterale della shell - (b) - che conta:

  • Con l'approccio / i , tutti i seguenti moduli sono EQUIVALENTI:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Con l'approccio (d) , tutte le seguenti forme sono EQUIVALENTI:

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

L'equivalenza è spiegata dall'elaborazione letterale stringa della shell :

Tutte le soluzioni di cui sopra danno come risultato la stessa stringa esatta (in ciascun gruppo) quando le cutvedono :

  • (s) : cutvede -d, come proprio argomento, seguito da un argomento separato che contiene un carattere spaziale - senza virgolette o \prefissi !.

  • (d) : cutvede -d più un carattere spaziale - senza virgolette o \prefissi! - come parte dello stesso argomento.

Il motivo per cui le forme nei rispettivi gruppi sono in definitiva identiche è duplice, basato su come la shell analizza i valori letterali delle stringhe :

  • La shell consente di specificare letterale così com'è tramite un meccanismo chiamato quoting , che può assumere diverse forme :
    • stringhe a virgoletta singola : il contenuto all'interno '...'è preso alla lettera e costituisce un singolo argomento
    • stringhe tra virgolette doppie : il contenuto all'interno "..."costituisce anche un singolo argomento, ma è soggetto a interpolazione (espande riferimenti variabili come $var, sostituzioni di comando ( $(...)o `...`) o espansioni aritmetiche ( $(( ... ))).
    • \-citazione di singoli personaggi : un carattere\ precedente che precede un singolo carattere fa interpretare quel personaggio come letterale.
  • La citazione è completata dalla rimozione delle virgolette , il che significa che una volta che la shell ha analizzato una riga di comando, rimuove i caratteri di citazione dagli argomenti (racchiudendo '...'o "..."o \istanze) - quindi, il comando che viene invocato non vede mai i caratteri di citazione .

36

Puoi anche dire:

cut -d\  -f 2

Si noti che ci sono due spazi dopo la barra rovesciata.


30
La persona che sa che "\" sfugge al personaggio successivo sarebbe molto attenta a notare cosa è successo dopo. Usare '\' per sfuggire a personaggi spaziali come questo è un linguaggio molto comune.
Jonathan Hartley,

3
@Jonathan Hartley generalmente la maggior parte dei codici è davvero illeggibile :)
Luca Borrione,

1
Dal punto di vista linux / unix, è \ stato il mio primo tentativo e ha funzionato. Sono d'accordo che è meno ovvio rispetto a ' ', ma sono sicuro che molti sono contenti di leggerlo qui come rassicurazione del comportamento. Per una migliore comprensione, vedere il commento di @ mklement0 di seguito.
tresf,

Correzione di @JonathanHartley: "la persona egoista che sa che" \ "sfugge al personaggio successivo e presume che anche tutti gli altri lo sappiano". Per i progetti personali ciò non si applica, ma in una squadra, tale presupposto è molto pericoloso (e potenzialmente costoso).
Eduard Nicodei,

1
@EduardNicodei Oh, sono d'accordo. Stavamo parlando di lettori del codice ("chi nota ...?"), Non di autori. Inoltre, su alcuni team è bene assumere un certo livello di competenza. Dipende dall'ambiente.
Jonathan Hartley,

5

Ho appena scoperto che puoi anche usare "-d ":

cut "-d "

Test

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
Anzi - o '-d '.
mklement0

3
Si noti che da cut's prospettiva tutti i seguenti sono identici: "-d ", '-d ', -d" ", -d' ', e -d\<space>: tutte le forme direttamente aggiungere l'argomento opzione (uno spazio) per l'opzione ( -d) e risultato nella stessa esatta stringa dal tempo cutli vede: una singola argomento contenente d seguito da uno spazio, dopo che la shell ha eseguito la rimozione della citazione
mklement0

1
La risposta di @ mklement0 dovrebbe essere la risposta. È il più completo in questa pagina (anche se è un commento).
tresf,

@QZSupport: apprezzo il sentimento e l'incoraggiamento: mi ha ispirato a pubblicare la mia risposta con ulteriori informazioni di base.
mklement0,

1
Lol scoperta affascinante!
Harry,

4

Non puoi farlo facilmente con cut se i dati hanno ad esempio più spazi. Ho trovato utile normalizzare l'input per un'elaborazione più semplice. Un trucco è usare sed per la normalizzazione come di seguito.

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

3

scut , un'utilità simile al taglio (più intelligente ma più lenta che ho creato) che può usare qualsiasi regex perl come token di rottura. L'interruzione dello spazio bianco è l'impostazione predefinita, ma puoi anche interrompere regex multi-carattere, regex alternativi, ecc.

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

quindi il comando sopra avrebbe spezzato le colonne negli spazi bianchi ed estratto le colonne (basate su 0) 6 2 8 7 in quell'ordine.


0

Ho una risposta (ammetto una risposta un po 'confusa) che coinvolge sed, espressioni regolari e gruppi di acquisizione:

  • \S* - prima parola
  • \s* - delimitatore
  • (\S*) - seconda parola - catturata
  • .* - resto della linea

Come sedespressione, il gruppo di acquisizione deve essere evaso, ovvero \(e \).

Le \1restituisce una copia del gruppo acquisito, vale a dire la seconda parola.

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

Quando guardi questa risposta, è un po 'confusa e, potresti pensare, perché preoccuparsi? Beh, spero che alcuni possano andare "Ah!" e utilizzerà questo modello per risolvere alcuni complessi problemi di estrazione del testo con una singola sedespressione.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.