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"
310
demandé sur Mateusz Piotrowski 2013-05-18 15:37:50

8 réponses

$ foo=${string#"$prefix"}
$ foo=${foo%"$suffix"}
$ echo "${foo}"
o-wor
454
répondu Adrian Frühwirth 2018-07-26 07:18:13

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:

  1. echo ne se soucie pas du nombre de chaînes dans sa liste d'arguments, et
  2. 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.

59
répondu Chris Kolodin 2016-08-09 17:01:49

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.

12
répondu Vladimir Petrakovich 2016-10-16 09:45:26

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!

12
répondu tommy.carstensen 2018-01-14 02:39:50

Petites et solution universelle:

expr "$string" : "$prefix\(.*\)$suffix"
6
répondu Tosi Do 2017-07-08 23:34:28

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
4
répondu math2001 2017-02-08 06:47:59

utilisant le =~ opérateur :

$ string="hello-world"
$ prefix="hell"
$ suffix="ld"
$ [[ $string =~ $prefix(.*)$suffix ]] && echo "${BASH_REMATCH[1]}"
o-wor
2
répondu Martin - マーチン 2018-01-12 05:14:43
$ 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.

1
répondu Vijay Vat 2018-09-08 10:13:59