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.
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 ':'
}
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.
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
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.
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]}
$ 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
.
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
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 .
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.
Bash verwenden.
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
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
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.
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.
for x in `echo $str | tr ";" "\n"`; do echo $x; done
eine lösung mit dem read builtin
IFS=':' read -a field <<< "1:2:3:4:5"
echo ${field[4]}
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
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