Supposons que j'ai la chaîne 1:2:3:4:5
et que je veux obtenir son dernier champ (5
dans ce cas). Comment puis-je utiliser Bash? J'ai essayé cut
, mais je ne sais pas comment spécifier le dernier champ avec -f
.
Vous pouvez utiliser opérateurs de chaîne :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
Cela coupe tout de l'avant jusqu'à un ':', goulûment.
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
Une autre méthode consiste à inverser avant et après cut
:
$ echo ab:cd:ef | rev | cut -d: -f1 | rev
ef
Il est donc très facile d’obtenir l’avant dernier champ ou toute plage de champs numérotés à partir de la fin.
Il est difficile d'obtenir le dernier champ en utilisant cut, mais voici (un ensemble de) solutions dans awk et 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
Dans l’hypothèse d’une utilisation assez simple (par exemple, pas d’échappement du délimiteur), vous pouvez utiliser grep:
$ echo "1:2:3:4:5" | grep -oE "[^:]+$"
5
Ventilation - trouvez tous les caractères, pas le délimiteur ([^:]) à la fin de la ligne ($). -o n'imprime que la partie correspondante.
Une manière:
var1="1:2:3:4:5"
var2=${var1##*:}
Un autre, en utilisant un tableau:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
var2=${var2[@]: -1}
Encore un autre avec un tableau:
var1="1:2:3:4:5"
saveIFS=$IFS
IFS=":"
var2=($var1)
IFS=$saveIFS
count=${#var2[@]}
var2=${var2[$count-1]}
Utilisation d'expressions régulières 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
Traduisez simplement le délimiteur en une nouvelle ligne et choisissez la dernière entrée avec tail -1
.
Utiliser 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
Si votre dernier champ est un seul caractère, vous pouvez faire ceci:
a="1:2:3:4:5"
echo ${a: -1}
echo ${a:(-1)}
Vérifiez manipulation de chaîne dans bash .
Il y a beaucoup de bonnes réponses ici, mais je veux tout de même partager celle-ci en utilisant nom de base:
basename $(echo "a:b:c:d:e" | tr ':' '/')
Cependant, il échouera s'il y a déjà des "/" dans votre chaîne. Si slash/est votre délimiteur, vous devez (et devriez) utiliser le nom de base.
Ce n'est pas la meilleure réponse mais cela montre simplement comment vous pouvez être créatif en utilisant les commandes bash.
Utilisation de Bash.
$ var1="1:2:3:4:0"
$ IFS=":"
$ set -- $var1
$ eval echo \$${#}
0
Si vous aimez python et avez la possibilité d'installer un paquet, vous pouvez utiliser cet utilitaire python .
# 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
Première utilisation, xargs le divise en utilisant ":", - n1 signifie que chaque ligne ne comporte qu'une partie. Ensuite, extrayez la dernière partie.
Pour ceux qui sont à l'aise avec Python, https://github.com/Russell91/pythonpy est un bon choix pour résoudre ce problème.
$ echo "a:b:c:d:e" | py -x 'x.split(":")[-1]'
Dans l'aide de pythonpy: -x treat each row of stdin as x
.
Avec cet outil, il est facile d’écrire du code python qui est appliqué à l’entrée.
for x in `echo $str | tr ";" "\n"`; do echo $x; done
une solution utilisant la lecture intégrée
IFS=':' read -a field <<< "1:2:3:4:5"
echo ${field[4]}
La correspondance des regex dans sed
est gourmande (va toujours à la dernière occurrence), que vous pouvez utiliser à votre avantage ici:
$ foo=1:2:3:4:5
$ echo ${foo} | sed "s/.*://"
5
La réponse pourrait être un peu tardive, bien qu'une solution simple consiste à inverser l'ordre de la chaîne d'entrée. Cela vous permettrait de toujours gagner le dernier élément, quelle que soit sa longueur.
[chris@desktop bin]$ echo 1:2:3:4:5 | rev | cut -d: -f1
5
Il est important de noter cependant que si vous utilisez cette méthode et que les nombres sont supérieurs à un chiffre (ou supérieurs à un caractère dans toutes les circonstances), vous devrez exécuter une autre commande "rev" sur la sortie redirigée.
[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
J'espère pouvoir aider, acclamations