risposta-alla-domanda-sullo-sviluppo-web-bd.com

Come trovare l'ultimo campo usando 'cut'

Senza usando sed o awk, only cut, come faccio ad ottenere l'ultimo campo quando il numero di campi è sconosciuto o cambia ad ogni linea?

204
noobcoder

Potresti provare qualcosa come questo:

echo 'maps.google.com' | rev | cut -d'.' -f 1 | rev

Spiegazione

  • il verso inverso di maps.google.com sarà moc.elgoog.spam
  • cut utilizza punto come delimitatore e sceglie il primo campo, che è moc
  • infine, lo invertiamo di nuovo (grazie per il promemoria, @tom) per ottenere com
472
zedfoxus

Utilizzare un parametro di espansione. Questo è molto più efficiente di qualsiasi tipo di comando esterno, cut (o grep) incluso.

data=foo,bar,baz,qux
last=${data##*,}

Vedi BashFAQ # 100 per un'introduzione alla manipolazione nativa delle stringhe in bash.

99
Charles Duffy

Non è possibile usare solo cut. Ecco un modo per usare grep:

grep -o '[^,]*$'

Sostituisci la virgola per altri delimitatori.

67
tom

Senza awk? ... Ma è così semplice con awk:

echo 'maps.google.com' | awk -F. '{print $NF}'

AWK è uno strumento molto più potente da avere in tasca .- F se per il campo separatorNF è il numero di campi (indica anche l'indice dell'ultimo)

18
Amir Mehler

Ci sono molti modi. Puoi usare anche questo.

echo "Your string here"| tr ' ' '\n' | tail -n1
> here

Ovviamente, l'input dello spazio vuoto per il comando tr deve essere sostituito con il delimitatore di cui hai bisogno.

12
rjni

Questa è l'unica soluzione possibile per l'utilizzo di nient'altro che tagliare:

echo "s.t.r.i.n.g." | taglia -d '.' -f2 - [repeat_following_part_forever_or_until_out_of_memory:] | taglia -d '.' -f2-

Usando questa soluzione, il numero di campi può effettivamente essere sconosciuto e variare di volta in volta. Tuttavia, poiché la lunghezza della linea non deve superare i caratteri oi campi LINE_MAX, incluso il carattere di nuova riga, un numero arbitrario di campi non può mai essere parte come una condizione reale di questa soluzione.

Sì, una soluzione molto sciocca ma l'unica che soddisfa i criteri che penso.

6
A friend

i seguenti strumenti Suggerimento di un amico

#!/bin/bash
rcut(){

  nu="$( echo $1 | cut -d"$DELIM" -f 2-  )"
  if [ "$nu" != "$1" ]
  then
    rcut "$nu"
  else
    echo "$nu"
  fi
}

$ export DELIM=.
$ rcut a.b.c.d
d
2
user2166700

Se si dispone di un file denominato filelist.txt che è un elenco percorsi come il seguente: C: /dir1/dir2/file1.h C: /dir1/dir2/dir3/file2.h

allora puoi fare questo: rev filelist.txt | cut -d "/" -f1 | rev

0
aperson1961

Se la stringa di input non contiene barre, puoi usare basename e una subshell:

$ basename "$(echo 'maps.google.com' | tr '.' '/')"

Questo non usa sed o awk ma non usa neanche cut, quindi non sono abbastanza sicuro se si qualifica come risposta alla domanda come formulata.

Questo non funziona bene se si elaborano stringhe di input che possono contenere barre in avanti. Una soluzione alternativa per quella situazione sarebbe quella di sostituire la barra in avanti con qualche altro carattere che, sai, non fa parte di una stringa di input valida. Ad esempio, il carattere pipe (|) non è consentito nei nomi dei file, quindi funzionerebbe:

$ basename "$(echo 'maps.google.com/some/url/things' | tr '/' '|' | tr '.' '/')" | tr '|' '/'
0
jstine

Aggiungere un approccio a questa vecchia domanda solo per il gusto di farlo:

$ cat input.file # file containing input that needs to be processed
a;b;c;d;e
1;2;3;4;5
no delimiter here
124;adsf;15454
foo;bar;is;null;info

$ cat tmp.sh # showing off the script to do the job
#!/bin/bash
delim=';'
while read -r line; do  
    while [[ "$line" =~ "$delim" ]]; do
        line=$(cut -d"$delim" -f 2- <<<"$line")
    done
    echo "$line"
done < input.file

$ ./tmp.sh # output of above script/processed input file
e
5
no delimiter here
15454
info

Oltre a bash, viene utilizzato solo il taglio. Bene, ed eco, immagino.

0
Kaffe Myers

Mi sono reso conto che se solo ci accertiamo che esista un delimitatore finale, funziona. Quindi nel mio caso ho delimitatori di virgola e spazi bianchi. Aggiungo uno spazio alla fine; $ ans="a, b" $ ans+=" "; echo ${ans} | tr ',' ' ' | tr -s ' ' | cut -d' ' -f2 b

0
AnneTheAgile