Risposte:
È possibile utilizzare gli operatori di stringa :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
Questo taglia tutto dal davanti fino a un ':', avidamente.
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
${foo%:*}
. #
- dall'inizio; %
- dalla fine. #
, %
- corrispondenza più breve; ##
, %%
- partita più lunga.
echo ${pwd##*/}
non funziona.
pwd
come una variabile. Prova dir=$(pwd); echo ${dir##*/}
. Per me va bene!
Un altro modo è di invertire prima e dopo cut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
Questo rende molto facile ottenere l'ultimo ma un campo, o qualsiasi intervallo di campi numerati dalla fine.
echo "1 2 3 4" | rev | cut -d " " -f1 | rev
rev
, era proprio quello di cui avevo bisogno! cut -b20- | rev | cut -b10- | rev
È difficile ottenere l'ultimo campo usando cut, ma qui ci sono alcune soluzioni in awk e perl
echo 1:2:3:4:5 | awk -F: '{print $NF}'
echo 1:2:3:4:5 | perl -F: -wane 'print $F[-1]'
/
carattere di finitura : /a/b/c/d
e /a/b/c/d/
producono lo stesso risultato ( d
) durante l'elaborazione pwd | awk -F/ '{print $NF}'
. La risposta accettata si traduce in un risultato vuoto nel caso di/a/b/c/d/
/
come delimitatore, e se il tuo percorso è /my/path/dir/
userà il valore dopo l'ultimo delimitatore, che è semplicemente una stringa vuota. Quindi è meglio evitare la barra finale se è necessario fare una cosa del genere.
awk '{$NF=""; print $0}' FS=: OFS=:
spesso funziona abbastanza bene.
Supponendo un utilizzo abbastanza semplice (nessuna evasione del delimitatore, per esempio), puoi usare grep:
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
Ripartizione: trova tutti i caratteri non il delimitatore ([^:]) alla fine della riga ($). -o stampa solo la parte corrispondente.
Senso unico:
var1="1:2:3:4:5"
var2=${var1##*:}
Un altro, usando un array:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
Ancora un altro con un array:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
Utilizzo delle espressioni regolari di Bash (versione> = 3.2):
var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e
Basta tradurre il delimitatore in una nuova riga e scegliere l'ultima voce con tail -1
.
\n
, ma per la maggior parte dei casi è la soluzione più leggibile.
Utilizzando sed
:
$ echo '1:2:3:4:5' | sed 's/.*://' # => 5
$ echo '' | sed 's/.*://' # => (empty)
$ echo ':' | sed 's/.*://' # => (empty)
$ echo ':b' | sed 's/.*://' # => b
$ echo '::c' | sed 's/.*://' # => c
$ echo 'a' | sed 's/.*://' # => a
$ echo 'a:' | sed 's/.*://' # => (empty)
$ echo 'a:b' | sed 's/.*://' # => b
$ echo 'a::c' | sed 's/.*://' # => c
Se il tuo ultimo campo è un singolo carattere, puoi farlo:
a="1:2:3:4:5"
echo ${a: -1}
echo ${a:(-1)}
Controlla la manipolazione delle stringhe in bash .
a
, non l'ultimo campo .
Ci sono molte buone risposte qui, ma voglio ancora condividere questo usando basename :
basename $(echo "a:b:c:d:e" | tr ':' '/')
Tuttavia fallirà se ci sono già alcuni '/' nella tua stringa . Se slash / è il delimitatore, allora devi (e dovresti) usare il nome di base.
Non è la risposta migliore ma mostra solo come puoi essere creativo usando i comandi bash.
Usando Bash.
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
echo ${!#}
invece di eval echo \$${#}
.
for x in `echo $str | tr ";" "\n"`; do echo $x; done
Per coloro che si sentono a proprio agio con Python, https://github.com/Russell91/pythonpy è una buona scelta per risolvere questo problema.
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
Dalla aiuto pythonpy: -x treat each row of stdin as x
.
Con quello strumento, è facile scrivere codice Python che viene applicato all'input.
Potrebbe essere un po 'in ritardo con la risposta, sebbene una soluzione semplice sia quella di invertire l'ordine della stringa di input. Ciò ti consentirebbe di ottenere sempre l'ultimo oggetto, indipendentemente dalla lunghezza.
[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5
È importante notare, tuttavia, se si utilizza questo metodo e i numeri sono più grandi di 1 cifra (o più grandi di un carattere in qualsiasi circostanza), sarà necessario eseguire un altro comando 'rev' sull'output del piping.
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[chris@desktop bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24
Spero di poterti aiutare, evviva
Se ti piace python e hai un'opzione per installare un pacchetto, puoi usare questa utility python .
# install pythonp
pythonp -m pip install pythonp
echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
pythonp
pacchetto è quello di farti fare le stesse cose python -c
con un minor numero di caratteri. Dai un'occhiata a README nel repository.
5
se la stringa è1:2:3:4:5:
(mentre usando gli operatori di stringa si ottiene un risultato vuoto). Ciò è particolarmente utile quando si analizzano percorsi che potrebbero contenere (o meno) un/
carattere finale .