Supprimer un préfixe/suffixe fixe d'une chaîne dans Bash
dans mon script bash
j'ai une chaîne et son préfixe/suffixe. Je dois supprimer le préfixe / suffixe de la chaîne originale.
Par exemple, disons que j'ai les valeurs suivantes:
string="hello-world"
prefix="hell"
suffix="ld"
Comment obtenir le résultat suivant?
result="o-wor"
8 réponses
$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor
utilisant sed:
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
dans la commande sed, le caractère ^
correspond au texte commençant par $prefix
, et le texte suivant $
correspond au texte se terminant par $suffix
.
Adrian Frühwirth fait quelques bons points dans les commentaires ci-dessous, mais sed
à cet effet peut être très utile. Le fait que le contenu de $préfixe et suffixe $sont interprétés par sed peut être bon OU mauvais, tant que vous fais attention, ça devrait aller. La beauté est, vous pouvez faire quelque chose comme ceci:
$ prefix='^.*ll'
$ suffix='ld$'
$ echo "$string" | sed -e "s/^$prefix//" -e "s/$suffix$//"
o-wor
qui peut être ce que vous voulez, et qui est à la fois plus fantaisiste et plus puissant que la substitution de variables de bash. Si vous vous souvenez qu'avec un grand pouvoir vient une grande responsabilité (comme dit Spiderman), vous devriez être bien.
une introduction rapide à sed peut être trouvée à http://evc-cit.info/cit052/sed_tutorial.html
Une note sur la coque et à son utilisation de chaînes de caractères:
pour l'exemple particulier donné, ce qui suit fonctionnerait aussi bien:
$ echo $string | sed -e s/^$prefix// -e s/$suffix$//
...mais seulement parce que:
- echo ne se soucie pas du nombre de chaînes dans sa liste d'arguments, et
- il n'y a pas d'Espaces Dans $prefix et $suffix
c'est généralement une bonne pratique de citer une chaîne la ligne de commande parce que même si elle contient des espaces, elle sera présentée à la commande comme un seul argument. Nous citons $ prefix et $suffix pour la même raison: chaque commande edit à sed sera passée comme une chaîne de caractères. Nous utilisons des guillemets doubles parce qu'ils permettent l'interpolation variable; si nous avions utilisé des guillemets simples, la commande sed aurait obtenu un $prefix
littéral et $suffix
ce qui n'est certainement pas ce que nous voulions.
noter, aussi, mon utilisation de citations simples quand paramétrage des variables prefix
et suffix
. Nous ne voulons certainement pas que quelque chose dans les ficelles soit interprété, donc nous les citons pour qu'aucune interpolation n'ait lieu. Encore une fois, il peut ne pas être nécessaire dans cet exemple, mais c'est une très bonne habitude à prendre.
j'utilise grep pour enlever les préfixes des chemins (qui ne sont pas bien gérés par sed
):
echo "$input" | grep -oP "^$prefix\K.*"
\K
supprime de la correspondance tous les caractères avant elle.
connaissez-vous la longueur de votre préfixe et de votre suffixe? Dans votre cas:
result=$(echo $string | cut -c5- | rev | cut -c3- | rev)
ou plus général:
result=$(echo $string | cut -c$((${#prefix}+1))- | rev | cut -c$((${#suffix}+1))- | rev)
mais la solution D'Adrian Frühwirth est trop cool! Je ne savais pas à ce sujet!
Petites et solution universelle:
expr "$string" : "$prefix\(.*\)$suffix"
en utilisant la réponse de @Adrian Frühwirth:
function strip {
local STRING=${1#$""}
echo ${STRING%$""}
}
utilisez - le comme ceci
HELLO=":hello:"
HELLO=$(strip "$HELLO" ":")
echo $HELLO # hello
utilisant le =~
opérateur :
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ [[ $string =~ $prefix(.*)$suffix ]] && echo "${BASH_REMATCH[1]}"
o-wor
$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ #remove "hell" from "hello-world" if "hell" is found at the beginning.
$ prefix_removed_string=${string/#$prefix}
$ #remove "ld" from "o-world" if "ld" is found at the end.
$ suffix_removed_String=${prefix_removed_string/%$suffix}
$ echo $suffix_removed_String
o-wor
Notes:
préfixe#$: ajouter # permet de s'assurer que la chaîne "hell" n'est supprimée que si elle se trouve au début. suffixe%$: l'ajout de % permet de s'assurer que la sous-couche "ld" est supprimée seulement si elle se trouve dans end.
sans ceux-ci, les sous-couches "hell" et "ld" seront enlevées partout, même il se trouve au milieu.