wake-up-neo.com

So teilen Sie eine Zeichenfolge in Shell und erhalten das letzte Feld

Angenommen, ich habe die Zeichenfolge 1:2:3:4:5 und möchte das letzte Feld (in diesem Fall 5) erhalten. Wie mache ich das mit Bash? Ich habe cut ausprobiert, weiß aber nicht, wie ich das letzte Feld mit -f angeben soll.

240
cd1

Sie können Stringoperatoren verwenden :

$ foo=1:2:3:4:5
$ echo ${foo##*:}
5

Das schneidet alles von vorne bis zu einem ':', gierig.

${foo  <-- from variable foo
  ##   <-- greedy front trim
  *    <-- matches anything
  :    <-- until the last ':'
 }
346
Stephen

Eine andere Möglichkeit besteht darin, vor und nach cut umzukehren:

$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef

Dies macht es sehr einfach, das vorletzte Feld oder einen Bereich von Feldern zu erhalten, die am Ende nummeriert sind.

314
a3nm

Es ist schwierig, das letzte Feld mit cut zu erhalten, aber hier sind (eine Reihe von) Lösungen in awk und Perl 

 $ echo 1: 2: 3: 4: 5 | awk -F: '{print $ NF}' 
 5 
 $ echo 1: 2: 3: 4: 5 | Perl -F: -wane 'print $ F [-1]' 
 5 
65
William Pursell

Angenommen, die Verwendung ist recht einfach (z. B. keine Begrenzung des Trennzeichens), Sie können grep verwenden:

$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5

Aufschlüsselung - Finde alle Zeichen, nicht das Trennzeichen ([^:]) am Ende der Zeile ($). -o druckt nur den passenden Teil.

25

Einweg:

var1="1:2:3:4:5"
var2=${var1##*:}

Ein anderes mit einem Array:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}

Noch ein anderes mit einem Array:

var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}

Verwenden von regulären Ausdrücken von Bash (Version> = 3.2):

var1="1:2:3:4:5"
[[ $var1 =~ :([^:]*)$ ]]
var2=${BASH_REMATCH[1]}
18
$ echo "a b c d e" | tr ' ' '\n' | tail -1
e

Übersetzen Sie das Trennzeichen einfach in einen Zeilenumbruch und wählen Sie den letzten Eintrag mit tail -1.

8
user3133260

sed verwenden:

$ 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
6
Rafael

Wenn Ihr letztes Feld ein einzelnes Zeichen ist, können Sie Folgendes tun:

a="1:2:3:4:5"

echo ${a: -1}
echo ${a:(-1)}

Überprüfen Sie die string-Bearbeitung in bash .

4
Ab Irato

Hier gibt es viele gute Antworten, aber ich möchte diese mit basename teilen:

 basename $(echo "a:b:c:d:e" | tr ':' '/')

Es wird jedoch fehlschlagen, wenn in Ihrem String bereits einige '/' enthalten sind. Wenn der Schrägstrich/Ihr Trennzeichen ist, müssen Sie (und sollten) nur den Basisnamen verwenden. 

Dies ist nicht die beste Antwort, sondern zeigt nur, wie Sie mit bash-Befehlen kreativ sein können.

3
021

Bash verwenden.

$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo  \$${#}
0
2
ghostdog74

Wenn Sie Python mögen und die Möglichkeit haben, ein Paket zu installieren, können Sie dieses Python-Dienstprogramm verwenden.

# install pythonp
pythonp -m pip install pythonp

echo "1:2:3:4:5" | pythonp "l.split(':')[-1]"
5
2
bombs
echo "a:b:c:d:e"|xargs -d : -n1|tail -1

Verwenden Sie xargs zunächst mit ":". - n1 bedeutet, dass jede Zeile nur einen Teil hat. Anschließend wird der letzte Teil gedruckt.

2
Crytis

Für diejenigen, die mit Python vertraut sind, ist https://github.com/Russell91/pythonpy eine gute Wahl, um dieses Problem zu lösen.

$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'

Aus der Pythonpy-Hilfe: -x treat each row of stdin as x.

Mit diesem Tool ist es einfach, Python-Code zu schreiben, der auf die Eingabe angewendet wird.

1
for x in `echo $str | tr ";" "\n"`; do echo $x; done
1
Nahid Akbar

eine lösung mit dem read builtin

IFS=':' read -a field <<< "1:2:3:4:5"
echo ${field[4]}
0
baz

Regex-Matching in sed ist gierig (geht immer bis zum letzten Vorkommen), das Sie hier zu Ihrem Vorteil nutzen können:

$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
0
slushy

Möglicherweise ist die Antwort etwas zu spät, eine einfache Lösung besteht jedoch darin, die Reihenfolge der Eingabezeichenfolge umzukehren. Auf diese Weise können Sie immer den letzten Gegenstand unabhängig von der Länge erhalten. 

[[email protected] bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5

Wenn Sie diese Methode verwenden und die Zahlen größer als eine Ziffer sind (oder unter allen Umständen größer als ein Zeichen), müssen Sie einen weiteren Befehl "rev" über die Pipe-Ausgabe ausführen.

[[email protected] bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1
42
[[email protected] bin]$ echo 1:2:3:4:5:8:24 | rev | cut -d: -f1 | rev
24

Ich hoffe ich kann helfen, Prost

0
Chris