Quelle est la façon la plus élégante de supprimer un chemin de la variable $PATH dans Bash?
ou plus généralement, Comment puis-je supprimer un élément d'une liste séparée par deux points dans une variable D'environnement Bash?
j'ai pensé que j'avais vu une façon simple de faire cela il y a des années, en utilisant les formes plus avancées de l'expansion variable de Bash, mais si c'est le cas, j'ai perdu la trace de celui-ci. Une recherche rapide de Google a produit étonnamment peu de résultats pertinents et aucun que je qualifierais de "simple" ou "élégant". Par exemple, deux méthodes utilisant sed et awk, respectivement:
PATH=$(echo $PATH | sed -e 's;:?/home/user/bin;;' -e 's;/home/user/bin:?;;')
PATH=!(awk -F: '{for(i=1;i<=NF;i++){if(!($i in a)){a[$i];printf s$i;s=":"}}}'<<<$PATH)
est - ce que rien de simple n'existe? Y a-t-il quelque chose d'analogue à une fonction split() dans Bash?
mise à jour:
Il semble que je doive m'excuser pour ma question intentionnellement vague; j'étais moins intéressé à résoudre un cas d'utilisation spécifique qu'à provoquer une bonne discussion. Heureusement, je l'ai eu!
il y a des techniques très intelligentes ici. En fin de compte, j'ai ajouté ce qui suit trois fonctions de ma boîte à outils. La magie se produit dans path_remove, qui est basé en grande partie sur L'utilisation Intelligente de Martin York de awk
'S RS variable.
path_append () { path_remove ; export PATH="$PATH:"; }
path_prepend () { path_remove ; export PATH=":$PATH"; }
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '"151910920" != "''"' | sed 's/:$//'`; }
la seule vraie miette là-dedans est l'utilisation de sed
pour enlever le colon traînant. Compte tenu de la simplicité du reste de la solution de Martin, cependant, je suis tout à fait prêt à vivre avec elle!
question connexe: comment manipuler les éléments $ PATH dans les scripts shell?
30 réponses
Une minute avec awk:
# Strip all paths with SDE in them.
#
export PATH=`echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}'`
Edit: It réponse aux commentaires ci-dessous:
$ export a="/a/b/c/d/e:/a/b/c/d/g/k/i:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i"
$ echo ${a}
/a/b/c/d/e:/a/b/c/d/f:/a/b/c/g:/a/b/c/d/g/i
## Remove multiple (any directory with a: all of them)
$ echo ${a} | awk -v RS=: -v ORS=: '/a/ {next} {print}'
## Works fine all removed
## Remove multiple including last two: (any directory with g)
$ echo ${a} | awk -v RS=: -v ORS=: '/g/ {next} {print}'
/a/b/c/d/e:/a/b/c/d/f:
## Works fine: Again!
modifier en réponse à un problème de sécurité: (qui n'est pas pertinent à la question)
export PATH=$(echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}' | sed 's/:*$//')
cela supprime tous les colons traînants laissés en supprimant les dernières entrées, qui ajouteraient effectivement .
à votre chemin.
Mon sale hack:
echo ${PATH} > t1
vi t1
export PATH=$(cat t1)
étant donné que le grand problème avec la substitution est la fin des cas, pourquoi ne pas faire en sorte que la fin des cas ne diffère pas des autres cas? Si le chemin avait déjà des colons au début et à la fin, nous pourrions simplement chercher notre chaîne désirée enveloppée de colons. Comme il est, nous pouvons facilement ajouter ces colons et les enlever après.
# PATH => /bin:/opt/a dir/bin:/sbin
WORK=:$PATH:
# WORK => :/bin:/opt/a dir/bin:/sbin:
REMOVE='/opt/a dir/bin'
WORK=${WORK/:$REMOVE:/:}
# WORK => :/bin:/sbin:
WORK=${WORK%:}
WORK=${WORK#:}
PATH=$WORK
# PATH => /bin:/sbin
Pur bash :).
Voici la solution la plus simple que je puisse imaginer:
#!/bin/bash
IFS=:
# convert it to an array
t=($PATH)
unset IFS
# perform any array operations to remove elements from the array
t=(${t[@]%%*usr*})
IFS=:
# output the new array
echo "${t[*]}"
l'exemple ci-dessus supprimera tout élément dans $PATH qui contient"usr". Vous pouvez remplacer "*usr*" par "/home/user/bin" pour supprimer l'élément.
mise à jour par sschuberth
même si je pense que les espaces dans un $PATH
sont une horrible idée, voici une solution que poignées:
PATH=$(IFS=':';t=($PATH);n=${#t[*]};a=();for ((i=0;i<n;i++)); do p="${t[i]%%*usr*}"; [ "${p}" ] && a[i]="${p}"; done;echo "${a[*]}");
ou
IFS=':'
t=($PATH)
n=${#t[*]}
a=()
for ((i=0;i<n;i++)); do
p="${t[i]%%*usr*}"
[ "${p}" ] && a[i]="${p}"
done
echo "${a[*]}"
voici un one-liner qui, malgré les réponses acceptées et les mieux notées , n'ajoute pas de caractères invisibles au chemin et peut faire face à des chemins qui contiennent des espaces:
export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/cygwin/" | tr "\n" ":"); echo ${p%:})
personnellement, je trouve aussi cela facile à lire / comprendre, et cela implique seulement des commandes communes au lieu d'utiliser awk.
"151910920 de la fonction" __chemin_remove(){
local D=": $ {PATH}:";
[ "/:$1:/:}" != "$D"] & & PATH= " ${D/:$1:/:}";
PATH= " $ {PATH/#:/}";
export PATH= " ${PATH/%:/}";
}
L'a trouvé dans le mien .dossier bashrc. Quand vous jouez avec PATH, et qu'il se perd, awk/sed / grep devient indisponible :-)
la meilleure option pure bash que j'ai trouvé jusqu'à présent est la suivante:
function path_remove {
PATH=${PATH/":"/} # delete any instances in the middle or at the end
PATH=${PATH/":"/} # delete any instances at the beginning
}
ceci est basé sur la réponse pas tout à fait correcte à ajouter répertoire à $PATH si elle n'est pas déjà là plus sur Superuser.
Voici une solution qui:
- est un pur Bash,
- n'invoque pas d'autres procédés (comme "sed" ou "awk"),
- ne change pas
IFS
, - n'est pas à la fourche d'un sous-shell,
- poignées de chemins avec des espaces, et
-
supprime toutes les occurrences de l'argument dans
PATH
.removeFromPath() { local p d p="::" d=":$PATH:" d=${d//$p/:} d=${d/#:/} PATH=${d/%:/} }
je viens d'utiliser les fonctions de la distribution bash, qui sont là apparemment depuis 1991. Ceux-ci sont toujours dans le paquet bash-docs sur Fedora, et étaient utilisés dans /etc/profile
, mais pas plus...
$ rpm -ql bash-doc |grep pathfunc
/usr/share/doc/bash-4.2.20/examples/functions/pathfuncs
$ cat $(!!)
cat $(rpm -ql bash-doc |grep pathfunc)
#From: "Simon J. Gerraty" <sjg@zen.void.oz.au>
#Message-Id: <199510091130.VAA01188@zen.void.oz.au>
#Subject: Re: a shell idea?
#Date: Mon, 09 Oct 1995 21:30:20 +1000
# NAME:
# add_path.sh - add dir to path
#
# DESCRIPTION:
# These functions originated in /etc/profile and ksh.kshrc, but
# are more useful in a separate file.
#
# SEE ALSO:
# /etc/profile
#
# AUTHOR:
# Simon J. Gerraty <sjg@zen.void.oz.au>
# @(#)Copyright (c) 1991 Simon J. Gerraty
#
# This file is provided in the hope that it will
# be of use. There is absolutely NO WARRANTY.
# Permission to copy, redistribute or otherwise
# use this file is hereby granted provided that
# the above copyright notice and this notice are
# left intact.
# is missing from (or PATH) ?
no_path() {
eval "case :$${2-PATH}: in *::*) return 1;; *) return 0;; esac"
}
# if exists and is not in path, append it
add_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$${2:-PATH}:"
}
# if exists and is not in path, prepend it
pre_path () {
[ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}=":$${2:-PATH}"
}
# if is in path, remove it
del_path () {
no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
sed -e "s;::;:;g" -e "s;^:;;" -e "s;:$;;"`
}
Eh bien, à bash, comme il soutient l'expression régulière, je ferais simplement:
PATH=${PATH/:\/home\/user\/bin/}
j'ai écrit une réponse à ce ici (en utilisant awk aussi). Mais je ne suis pas certain de ce que vous recherchez? Il me semble au moins clair ce qu'il fait, au lieu d'essayer de rentrer dans une ligne. Pour une simple doublure, cependant, qui enlève seulement des trucs, je recommande
echo $PATH | tr ':' '\n' | awk '"151900920" != "/bin"' | paste -sd:
remplace
echo $PATH | tr ':' '\n' |
awk '"151910920" != "/bin"; "151910920" == "/bin" { print "/bar" }' | paste -sd:
ou (plus court mais moins lisible)
echo $PATH | tr ':' '\n' | awk '"151920920" == "/bin" { print "/bar"; next } 1' | paste -sd:
en tout cas, pour la même question, et un grand nombre de réponses utiles, voir ici .
Oui, mettre un côlon à la fin du chemin, par exemple, rend enlever un chemin un peu moins maladroit et sujet aux erreurs.
path_remove () {
declare i newPATH
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
#echo ${@:${i}:1}
newPATH="${newPATH//${@:${i}:1}:/}"
done
export PATH="${newPATH%:}"
return 0;
}
path_remove_all () {
declare i newPATH
shopt -s extglob
newPATH="${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//+(${@:${i}:1})*([^:]):/}"
#newPATH="${newPATH//+(${@:${i}:1})*([^:])+(:)/}"
done
shopt -u extglob
export PATH="${newPATH%:}"
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
si vous vous souciez de supprimer les doublons dans $PATH, la façon la plus élégante, IMHO, serait de ne pas les ajouter en premier lieu. En 1 ligne:
if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$folder" ) ; then PATH=$PATH:$folder ; fi
$dossier peut être remplacé par quelque chose, et peut contenir des espaces ("/home/user/mes documents")
la solution la plus élégante que j'ai trouvée à ce jour:
pathrm () {
local IFS=':'
local newpath
local dir
local pathvar=${2:-PATH}
for dir in ${!pathvar} ; do
if [ "$dir" != "" ] ; then
newpath=${newpath:+$newpath:}$dir
fi
done
export $pathvar="$newpath"
}
pathprepend () {
pathrm
local pathvar=${2:-PATH}
export $pathvar="${!pathvar:+:${!pathvar}}"
}
pathappend () {
pathrm
local pathvar=${2:-PATH}
export $pathvar="${!pathvar:+${!pathvar}:}"
}
la plupart des autres solutions proposées reposent uniquement sur l'appariement des chaînes et ne tiennent pas compte des segments de chemin contenant des noms spéciaux comme .
, ..
ou ~
. La fonction bash ci-dessous résout les chaînes de répertoires dans son argument et dans les segments de chemin pour trouver les correspondances de répertoires logiques aussi bien que les correspondances de chaînes.
rm_from_path() {
pattern=""
dir=''
[ -d "${pattern}" ] && dir="$(cd ${pattern} && pwd)" # resolve to absolute path
new_path=''
IFS0=${IFS}
IFS=':'
for segment in ${PATH}; do
if [[ ${segment} == ${pattern} ]]; then # string match
continue
elif [[ -n ${dir} && -d ${segment} ]]; then
segment="$(cd ${segment} && pwd)" # resolve to absolute path
if [[ ${segment} == ${dir} ]]; then # logical directory match
continue
fi
fi
new_path="${new_path}${IFS}${segment}"
done
new_path="${new_path/#${IFS}/}" # remove leading colon, if any
IFS=${IFS0}
export PATH=${new_path}
}
Test:
$ mkdir -p ~/foo/bar/baz ~/foo/bar/bif ~/foo/boo/bang
$ PATH0=${PATH}
$ PATH=~/foo/bar/baz/.././../boo/././../bar:${PATH} # add dir with special names
$ rm_from_path ~/foo/boo/../bar/. # remove same dir with different special names
$ [ ${PATH} == ${PATH0} ] && echo 'PASS' || echo 'FAIL'
j'aime les trois fonctions présentées dans la mise à jour de @BenBlank à sa question originale. Pour les généraliser, j'utilise une forme à 2 arguments, qui me permet de définir le chemin ou toute autre variable d'environnement que je veux:
path_append () { path_remove ; export ="${!1}:"; }
path_prepend () { path_remove ; export =":${!1}"; }
path_remove () { export ="`echo -n ${!1} | awk -v RS=: -v ORS=: ' != "''"' | sed 's/:$//'`"; }
exemples d'utilisation:
path_prepend PATH /usr/local/bin
path_append PERL5LIB "$DEVELOPMENT_HOME/p5/src/perlmods"
notez que j'ai aussi ajouté quelques guillemets pour permettre le traitement correct des noms de chemins qui contiennent des espaces.
Quelle est la façon la plus élégante de supprimer un chemin de la variable $PATH dans Bash?
quoi de plus élégant qu'awk?
path_remove () { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '"151900920" != "''"' | sed 's/:$//'`;
Python! C'est une solution plus lisible et maintenable, et il est facile d'inspecter pour voir qu'il fait vraiment ce que vous voulez.
voulez-vous supprimer le premier élément de chemin?
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
(au lieu de la tuyauterie de echo
, os.getenv['PATH']
serait un peu plus courte, et fourni le même résultat que ci-dessus, mais je suis inquiet que Python pourrait faire quelque chose avec cette variable d'environnement, il est donc probablement préférable de la pipe directement à partir de l'environnement dont vous vous souciez.)
de même pour supprimer de la fin:
PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
pour rendre ces fonctions shell réutilisables que vous pouvez, par exemple, coller dans votre .fichier bashrc:
strip_path_first () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[0]; print(':'.join(path))")"
}
strip_path_last () {
PATH="$(echo "$PATH" |
python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"
}
puisque cela tend à être assez problématique, car il N'y a pas de manière élégante, je recommande d'éviter le problème en réarrangeant la solution: construisez votre chemin vers le haut plutôt que de tenter de le démolir.
je pourrais être plus précis si je connaissais votre vrai contexte de problème. Dans l'intervalle, j'utiliserai une construction logicielle comme contexte.
un problème commun avec les constructions de logiciel est qu'il casse sur certaines machines, finalement en raison de la façon dont quelqu'un a configuré leur shell par défaut (chemin et autres variables d'environnement). La solution élégante est de rendre vos scripts de construction immunisés en spécifiant complètement l'environnement shell. Codez vos scripts de construction pour définir le chemin et d'autres variables d'environnement basées sur l'assemblage des pièces que vous contrôlez, telles que l'emplacement du compilateur, des bibliothèques, des outils, des composants, etc. Faites de chaque élément configurable quelque chose que vous pouvez individuellement définir, vérifier, puis utiliser de manière appropriée dans votre script.
par exemple, j'ai une construction Java basée sur Maven et ciblée sur le Web, dont j'ai hérité de mon nouvel employeur. Le script de construction est connu pour être fragile, et un autre nouvel employé et moi avons passé trois semaines (pas à temps plein, juste ici et là, mais encore de nombreuses heures) pour le faire fonctionner sur nos machines. Une étape essentielle était que j'ai pris le contrôle du chemin pour que je sache exactement quel Java, quel Maven, et quel WebLogic était invoqué. J'ai créé des variables d'environnement pour pointer chacun de ces outils, puis j'ai calculé le chemin basé sur ceux plus quelques autres. Des techniques similaires ont dompté les autres paramètres configurables, jusqu'à ce que nous ayons finalement créé une construction reproductible.
au fait, N'utilisez pas Maven, Java est correct, et n'achetez WebLogic que si vous avez absolument besoin de son clustering (mais sinon non, et surtout pas ses fonctionnalités propriétaires).
meilleurs voeux.
comme avec @litb, j'ai répondu à la question " comment manipuler les éléments $PATH dans les scripts shell ", donc ma réponse principale est là.
la fonctionnalité" split "de bash
et d'autres dérivés de la coque Bourne est parfaitement réalisée avec $IFS
, le séparateur inter-champs. Par exemple, pour définir les arguments de position ( ,
, ...) aux éléments de PATH, utilisez:
set -- $(IFS=":"; echo "$PATH")
ça va marcher tant qu'il n'y a pas d'Espaces Dans $PATH. Le faire fonctionner pour des éléments de chemin contenant des espaces est un exercice non-trivial-laissé pour le lecteur intéressé. Il est probablement plus simple de le traiter en utilisant un langage de script tel que Perl.
j'ai aussi un script, clnpath
, que j'utilise beaucoup pour définir mon chemin. Je l'ai documenté dans la réponse à " "Comment éviter de dupliquer la variable PATH dans csh ".
ce qui rend ce problème ennuyeux sont les cas de fencepost entre le premier et le dernier éléments. Le problème peut être résolu avec élégance en changeant de SI et en utilisant un tableau, mais je ne sais pas comment réintroduire le deux-points une fois que le chemin est converti en forme de tableau.
Voici une version légèrement moins élégante qui supprime un répertoire de $PATH
en utilisant la manipulation de chaîne seulement. Je l'ai testé.
#!/bin/bash
#
# remove_from_path dirname
#
# removes from user's $PATH
if [ $# -ne 1 ]; then
echo "Usage: "151900920" pathname" 1>&2; exit 1;
fi
delendum=""
NEWPATH=
xxx="$IFS"
IFS=":"
for i in $PATH ; do
IFS="$xxx"
case "$i" in
"$delendum") ;; # do nothing
*) [ -z "$NEWPATH" ] && NEWPATH="$i" || NEWPATH="$NEWPATH:$i" ;;
esac
done
PATH="$NEWPATH"
echo "$PATH"
Voici une chemise Perl:
PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$##;print' /home/usr/bin`
la variable $a
obtient le chemin à supprimer. Les commandes s
(substitute) et print
fonctionnent implicitement sur la variable $_
.
C'est bien. J'utilise celui-ci pour éviter d'ajouter des dupes en premier lieu.
#!/bin/bash
#
######################################################################################
#
# Allows a list of additions to PATH with no dupes
#
# Patch code below into your $HOME/.bashrc file or where it
# will be seen at login.
#
# Can also be made executable and run as-is.
#
######################################################################################
# add2path=($HOME/bin .) ## uncomment space separated list
if [ $add2path ]; then ## skip if list empty or commented out
for nodup in ${add2path[*]}
do
case $PATH in ## case block thanks to MIKE511
$nodup:* | *:$nodup:* | *:$nodup ) ;; ## if found, do nothing
*) PATH=$PATH:$nodup ## else, add it to end of PATH or
esac ## *) PATH=$nodup:$PATH prepend to front
done
export PATH
fi
## debug add2path
echo
echo " PATH == $PATH"
echo
avec globbing étendu permis il est possible de faire ce qui suit:
# delete all /opt/local paths in PATH
shopt -s extglob
printf "%s\n" "${PATH}" | tr ':' '\n' | nl
printf "%s\n" "${PATH//+(\/opt\/local\/)+([^:])?(:)/}" | tr ':' '\n' | nl
man bash | less -p extglob
Extended "globbing" one-liner (enfin, en quelque sorte):
path_remove () { shopt -s extglob; PATH="${PATH//+()+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; }
il ne semble pas nécessaire d'échapper à des coupures de 1$.
path_remove () { shopt -s extglob; declare escArg="${1//\//\/}"; PATH="${PATH//+(${escArg})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; }
ajouter des colons au chemin nous pourrions aussi faire quelque chose comme:
path_remove () {
declare i newPATH
# put a colon at the beginning & end AND double each colon in-between
newPATH=":${PATH//:/::}:"
for ((i=1; i<=${#@}; i++)); do
#echo ${@:${i}:1}
newPATH="${newPATH//:${@:${i}:1}:/}" # s/:\/fullpath://g
done
newPATH="${newPATH//::/:}"
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove_all () {
declare i newPATH extglobVar
extglobVar=0
# enable extended globbing if necessary
[[ ! $(shopt -q extglob) ]] && { shopt -s extglob; extglobVar=1; }
newPATH=":${PATH}:"
for ((i=1; i<=${#@}; i++ )); do
newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" # s/:\/path[^:]*//g
done
newPATH="${newPATH#:}" # remove leading colon
newPATH="${newPATH%:}" # remove trailing colon
# disable extended globbing if it was enabled in this function
[[ $extglobVar -eq 1 ]] && shopt -u extglob
unset PATH
PATH="${newPATH}"
export PATH
return 0
}
path_remove /opt/local/bin /usr/local/bin
path_remove_all /opt/local /usr/local
Dans path_remove_all (par proxxy):
-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}"
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}" # s/:\/path[^:]*//g
bien que ce soit un fil très ancien, j'ai pensé que cette solution pourrait être d'intérêt:
PATH="/usr/lib/ccache:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games"
REMOVE="ccache" # whole or part of a path :)
export PATH=$(IFS=':';p=($PATH);unset IFS;p=(${p[@]%%$REMOVE});IFS=':';echo "${p[*]}";unset IFS)
echo $PATH # outputs /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games
trouvé sur ce post de blog . Je pense que je l'aime plus :)
j'ai adopté une approche légèrement différente de celle de la plupart des gens ici et je me suis concentré spécifiquement sur la manipulation de cordes, comme ceci:
path_remove () {
if [[ ":$PATH:" == *"::"* ]]; then
local dirs=":$PATH:"
dirs=${dirs/::/:}
export PATH="$(__path_clean $dirs)"
fi
}
__path_clean () {
local dirs=${1%?}
echo ${dirs#?}
}
ce qui précède est un exemple simplifié des fonctions finales que j'utilise. J'ai aussi créé path_add_before
et path_add_after
vous permettant d'insérer un chemin avant/après un chemin spécifié déjà dans le chemin.
L'ensemble des fonctions sont disponibles en path_helpers.sh in my fichiers de configuration utilisateur . Ils supportent totalement la suppression/ajout/pré-ajout/insertion au début/milieu / fin de la chaîne de chemin.
le": "est causé par le fait que vous définissez la fin de ligne, pas le séparateur. J'utilise des unités de ressources limitées et j'aime tout emballer dans un seul script, sans ces bizarreries:
path_remove () {
PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '"151900920" != "''"{print s _ "151900920";s=":"}')"
}
c'est certes élégant, mais il utilise le sed externe. En outre, il supprime tous les chemins contenant la chaîne de recherche $1. Il ne laisse pas non plus de balancier : à la fin dans le cas où le chemin enlevé est le dernier sur le chemin.
PATH=`echo $PATH | sed 's/:[^:]*[^:]*//g'`
cette alternative laisse une finale pendante : cependant.
PATH=`echo $PATH | tr ":" "\n" | grep -v | tr "\n" ":"`
Les solutions de rechange sans backticks sont:
PATH=$(echo $PATH | sed 's/:[^:]*[^:]*//g')
PATH=$(echo $PATH | tr ":" "\n" | grep -v | tr "\n" ":")