Je voudrais supprimer le dernier caractère d'une chaîne, j'ai essayé ce petit script:
#! /bin/sh
t="lkj"
t=${t:-2}
echo $t
mais il affiche "lkj", qu'est-ce que je fais mal?
Dans un shell POSIX, la syntaxe ${t:-2}
Signifie quelque chose de différent - elle se développe à la valeur de t
si t
est définie et non nulle, et sinon à la valeur 2
. Pour découper un seul caractère par expansion de paramètre, la syntaxe que vous souhaitez probablement est ${t%?}
Notez que dans ksh93
, bash
ou zsh
, ${t:(-2)}
ou ${t: -2}
(Notez l'espace) sont légaux en tant qu'extension de sous-chaîne mais ne sont probablement pas ce que vous voulez, car ils retournent la sous-chaîne à partir d'une position à 2 caractères de la fin (c'est-à-dire qu'elle supprime le premier caractère i
de la chaîne ijk
).
Voir la section Expansion des paramètres du shell du manuel de référence Bash pour plus d'informations:
Avec bash
4.2 et supérieur, vous pouvez faire:
${var::-1}
Exemple:
$ a=123
$ echo "${a::-1}"
12
Notez que pour les anciens bash
(par exemple, bash 3.2.5
sur OS X), vous devez laisser des espaces entre et après les deux-points:
${var: : -1}
L'utilisation de sed devrait être aussi rapide que
sed 's/.$//'
Votre single echo est alors echo ljk | sed 's/.$//'
.
En utilisant cela, la chaîne d'une ligne peut être de n'importe quelle taille.
pour supprimer les derniers n
caractères d'une ligne qui n'utilise pas sed
OR awk
:
> echo lkj | rev | cut -c (n+1)- | rev
par exemple, vous pouvez supprimer le dernier caractère one character
en utilisant ceci:
> echo lkj | rev | cut -c 2- | rev
> lk
à partir de la page de manuel de rev
:
LA DESCRIPTION
L'utilitaire rev copie les fichiers spécifiés sur la sortie standard, inversant l'ordre des caractères sur chaque ligne. Si aucun fichier n'est spécifié, l'entrée standard est lue.
MISE À JOUR:
si vous ne connaissez pas la longueur de la chaîne, essayez:
$ x="lkj"
$ echo "${x%?}"
lk
Quelques options selon le Shell:
t=${t%?}
t=`expr " $t" : ' \(.*\).'`
t=${t[1,-2]}
t=${t:0:-1}
t=${t:0:${#t}-1}
t=${t/%?}
t=${t/~(E).$/}
@ {t=$1} ~~ $t *?
Notez que bien que tous soient censés supprimer le dernier caractère, vous constaterez que certaines implémentations (celles qui ne prennent pas en charge les caractères multi-octets) suppriment le dernier octet à la place (ainsi corromprait probablement le dernier caractère s'il était multi-octet).
La variante expr
suppose que $t
Ne se termine pas par plus d'un caractère de nouvelle ligne. Il retournera également un état de sortie non nul si la chaîne résultante finit par être 0
(Ou 000
Ou même -0
Avec certaines implémentations). Il pourrait également donner des résultats inattendus si la chaîne contient des caractères non valides.
La réponse la plus portable et la plus courte est presque certainement:
${t%?}
Cela fonctionne dans bash, sh, ash, dash, busybox/ash, zsh, ksh, etc.
Il fonctionne en utilisant l'expansion des paramètres Shell à l'ancienne. Plus précisément, le %
Spécifie de supprimer le plus petit suffixe correspondant du paramètre t
qui correspond au modèle global ?
(C'est-à-dire n'importe quel caractère).
Voir "Supprimer le plus petit motif de suffixe" ici pour une explication (beaucoup) plus détaillée et plus d'informations. Consultez également la documentation de votre shell (par exemple: man bash
) Sous "Extension des paramètres".
En remarque, si vous vouliez supprimer le premier caractère à la place, vous utiliseriez ${t#?}
, Car #
correspond à l'avant de la chaîne (préfixe) au lieu de l'arrière (suffixe).
Il convient également de noter que les versions %
Et #
Et %%
Et ##
, Qui correspondent aux plus longues version du modèle donné au lieu de la plus courte. ${t%%?}
Et ${t##?}
Feraient tous les deux la même chose que leur opérateur unique dans ce cas, (donc n'ajoutez pas le caractère supplémentaire inutile). Cela est dû au fait que le modèle ?
Donné ne correspond qu'à un seul caractère. Mélangez un *
Avec des caractères non génériques et les choses deviennent plus intéressantes avec %%
Et ##
.
Comprendre les extensions de paramètres, ou du moins connaître leur existence et savoir comment les rechercher, est incroyablement utile pour écrire et déchiffrer des scripts Shell de nombreuses versions. Les extensions de paramètres ressemblent souvent à des arcanes vaudou Shell pour beaucoup de gens parce que ... eh bien ... ils sont arcanes vaudou Shell (bien que très bien documentés si vous connaissez rechercher "expansion des paramètres"). Certainement bien d'avoir dans la ceinture à outils lorsque vous êtes coincé dans un Shell, cependant.
t=lkj
echo ${t:0:${#t}-1}
Vous obtenez une sous-chaîne de 0 à la longueur de chaîne -1. Notez cependant que cette soustraction est spécifique à bash et ne fonctionnera pas sur d'autres shells.
Par exemple, dash
n'est pas capable d'analyser même
echo ${t:0:$(expr ${#t} - 1)}
Par exemple, sur Ubuntu, /bin/sh
est dash
Vous pouvez également utiliser head
pour imprimer tout sauf le dernier caractère.
$ s='i am a string'
$ news=$(echo -n $s | head -c -1)
$ echo $news
i am a strin
Mais malheureusement, certaines versions de head
n'incluent pas le premier -
option. C'est le cas pour le head
fourni avec OS X.
Il est assez facile de le faire en utilisant une expression régulière:
n=2
echo "lkj" | sed "s/\(.*\).\{$n\}/\1/"
Merci SteelDriver et Networker!
si vous ne connaissez pas la longueur de la chaîne, essayez:
$ x="lkj"
$ echo "${x%?}"
lk
Quelques raffinements. Pour supprimer plusieurs caractères, vous pouvez ajouter plusieurs points d'interrogation. Par exemple, pour supprimer les deux derniers caractères de la variable: $SRC_IP_MSG
, vous pouvez utiliser:
SRC_IP_MSG=${SRC_IP_MSG%??}
Juste pour compléter quelques utilisations possibles de bash pur:
#!/bin/bash
# Testing substring removal
STR="Exemple string with trailing whitespace "
echo "'$STR'"
echo "Removed trailing whitespace: '${STR:0:${#STR}-1}'"
echo "Removed trailing whitespace: '${STR/%\ /}'"
La première syntaxe prend une sous-chaîne d'une chaîne, la syntaxe est${STRING:OFFSET:LENGTH}
Pour le second, notez le %
signe, ce qui signifie "de fin de ligne" et la syntaxe est${STRING/PATTERN/SUBSTITUTION}
Et voici deux formes plus courtes de celles mentionnées ci-dessus
echo "Removed trailing whitespace: '${STR::-1}'"
echo "Removed trailing whitespace: '${STR%\ }'"
Ici, remarquez à nouveau le %
signe, signifiant 'Supprimer (c'est-à-dire remplacer par' ') le motif correspondant le plus court (ici représenté par un espace d'échappement '\' à partir de la fin du paramètre [~ # ~] [~ # ~] - ici nommé [~ # ~] str [~ # ~]
Comme nous pouvons également utiliser php en ligne de commande, ou des scripts Shell. Il est parfois utile pour l'analyse chirurgicale.
php -r "echo substr('Hello', 0, -1);"
// Output hell
Avec passepoil:
echo "hello" | php -r "echo substr(trim(fgets(STDIN)), 0, -1);"
// Output hell