Question

Ou plus généralement, comment puis-je supprimer un élément d'une liste séparée-virgule dans une variable d'environnement Bash?

Je pensais avoir vu un moyen simple de faire il y a des années, en utilisant les formes plus avancées d'expansion variables Bash, mais si j'ai donc perdu la trace. Une recherche rapide de Google se étonnamment peu de résultats pertinents et que je ne qualifierais « 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)

Ne EXISTE rien simple? Y at-il quelque chose d'analogue à une fonction split () dans Bash?

Mise à jour: On dirait que je dois présenter mes excuses pour ma question intentionnellement vague; Je suis moins intéressé par la résolution d'un cas d'utilisation spécifique que à provoquer une bonne discussion. Heureusement, je l'ai!

Il y a quelques ici des techniques très intelligentes. En fin de compte, je l'ai ajouté les trois fonctions suivantes à ma boîte à outils. La magie se produit dans path_remove, qui repose en grande partie sur l'utilisation intelligente de Martin York variable RS de awk.

path_append ()  { path_remove $1; export PATH="$PATH:$1"; }
path_prepend () { path_remove $1; export PATH="$1:$PATH"; }
path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; }

La seule vraie cochonneries là est l'utilisation de pour enlever le sed deux points de fuite. Considérant la façon simple le reste de la solution de Martin est, bien, je suis prêt à vivre avec elle!


question connexe: How-je manipuler $ PATH éléments dans les scripts shell

Était-ce utile?

La solution

Une minute avec awk:

# Strip all paths with SDE in them.
#
export PATH=`echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}'`

Edit: Il 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é: (ce n'est pas pertinente à la question)

export PATH=$(echo ${PATH} | awk -v RS=: -v ORS=: '/SDE/ {next} {print}' | sed 's/:*$//')

Cela supprime toutes les deux points de suivi gauche en supprimant les dernières entrées, ce qui ajouterait effectivement à votre chemin ..

Autres conseils

Mon bidouille:

echo ${PATH} > t1
vi t1
export PATH=$(cat t1)

Depuis le gros problème avec la substitution est le cas de fin, que diriez-vous faire les affaires de fin ne différentes aux autres cas? Si le chemin avait déjà au début côlons et à la fin, nous pourrions simplement chercher notre chaîne désirée enveloppé avec deux points. Comme il est, nous pouvons facilement ajouter ces deux points et les enlever par la suite.

# 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

bash pur.)

Voici la solution la plus simple que je peux concevoir:

#!/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 effacera tout élément dans $ PATH qui contient « usr ». Vous pouvez remplacer "* usr *" avec "/ home / user / bin" pour supprimer tout cet élément.

mise à jour par sschuberth

Même si je pense que les espaces dans un sont un $PATH horribles idée, voici une solution qu'il gère:

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 une seule ligne qui, malgré le courant accepté et réponses les mieux notées, ne pas ajouter des caractères invisibles à PATH et peuvent faire face à des chemins contenant des espaces:

export PATH=$(p=$(echo $PATH | tr ":" "\n" | grep -v "/cygwin/" | tr "\n" ":"); echo ${p%:})

Personnellement, je trouve aussi ce facile à lire / comprendre, et il ne porte que sur les commandes communes au lieu d'utiliser awk.

Voici une solution:

  • est Bash pur,
  • ne pas invoquer d'autres processus (comme 'sed' ou 'awk'),
  • ne change pas IFS,
  • ne fourche pas un sous-shell,
  • gère les chemins avec des espaces et
  • supprime toutes les occurrences de l'argument en PATH.

    removeFromPath() {
       local p d
       p=":$1:"
       d=":$PATH:"
       d=${d//$p/:}
       d=${d/#:/}
       PATH=${d/%:/}
    }
  

fonction __path_remove () {
     D = local ": $ {PATH}:";
     [ "$ {D /: 1 $: /:}" = "$ D"!] && PATH = "$ {D /: 1 $: /:}";
     PATH = "$ {PATH / #: /}";
     export PATH = "$ {PATH /%: /}";
  }

Dug dehors de mon .bashrc. Lorsque vous jouez avec PATH, et il se perd, awk / sed / grep devient indisponible: -)

La meilleure option bash pur que j'ai trouvé à ce jour est le suivant:

function path_remove {
  PATH=${PATH/":$1"/} # delete any instances in the middle or at the end
  PATH=${PATH/"$1:"/} # delete any instances at the beginning
}

Ceci est basé sur le pas de réponse tout à fait correcte Ajouter un répertoire au PATH $ si elle est pas déjà sur le super-utilisateur.

Je viens en utilisant les fonctions de la distribution de bash, qui ont été là apparemment depuis 1991. Ce sont encore dans le paquet bash-docs sur Fedora, et utilisé pour être utilisé 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 $1 missing from $2 (or PATH) ?
no_path() {
        eval "case :\$${2-PATH}: in *:$1:*) return 1;; *) return 0;; esac"
}
# if $1 exists and is not in path, append it
add_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="\$${2:-PATH}:$1"
}
# if $1 exists and is not in path, prepend it
pre_path () {
  [ -d ${1:-.} ] && no_path $* && eval ${2:-PATH}="$1:\$${2:-PATH}"
}
# if $1 is in path, remove it
del_path () {
  no_path $* || eval ${2:-PATH}=`eval echo :'$'${2:-PATH}: |
    sed -e "s;:$1:;:;g" -e "s;^:;;" -e "s;:\$;;"`
}

J'ai écrit une réponse à cette ici (en utilisant awk aussi). Mais je ne suis pas sûr que ce que vous cherchez? Il semble au moins clair pour moi ce qu'il fait, au lieu d'essayer d'entrer dans une ligne. Pour une simple doublure, cependant, qui ne supprime que des choses, je recommande

echo $PATH | tr ':' '\n' | awk '$0 != "/bin"' | paste -sd:

Le remplacement est

echo $PATH | tr ':' '\n' | 
    awk '$0 != "/bin"; $0 == "/bin" { print "/bar" }' | paste -sd:

ou (plus court et moins lisible)

echo $PATH | tr ':' '\n' | awk '$0 == "/bin" { print "/bar"; next } 1' | paste -sd:

Quoi qu'il en soit, pour la même question, et beaucoup de réponses utiles, voir .

Eh bien, en bash, comme il soutient l'expression régulière, je voudrais simplement faire:

PATH=${PATH/:\/home\/user\/bin/}
  

Quelle est la manière la plus élégante de supprimer un chemin de la variable $ PATH dans Bash?

Ce qui est plus élégant que awk?

path_remove ()  { export PATH=`echo -n $PATH | awk -v RS=: -v ORS=: '$0 != "'$1'"' | sed 's/:$//'`; 

Python! Il est une solution plus lisible et maintenable, et il est facile d'inspecter les lieux pour que ça fait vraiment ce que vous voulez.

Dites que vous voulez 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, serait un os.getenv['PATH'] peu plus court, et à condition que 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 tuyau directement à partir de l'environnement que vous aimez.)

De la même façon à supprimer de la fin:

PATH="$(echo "$PATH" | python -c "import sys; path = sys.stdin.read().split(':'); del path[-1]; print(':'.join(path))")"

Pour 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))")"
}

Oui, mettre deux points à la fin de PATH, par exemple, permet la suppression d'un chemin

un peu moins maladroit et sujette 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 êtes préoccupé par la suppression des doublons dans $ PATH, la façon la plus élégante, à mon humble avis, serait de ne pas les ajouter en premier lieu. Dans une ligne:

if ! $( echo "$PATH" | tr ":" "\n" | grep -qx "$folder" ) ; then PATH=$PATH:$folder ; fi

dossier $ peut être remplacé par quoi que ce soit, et peut contenir des espaces ( "/ home / user / mes documents")

La solution la plus élégante bash pur que j'ai trouvé à ce jour:

pathrm () {                                                                      
  local IFS=':'                                                                  
  local newpath                                                                  
  local dir                                                                      
  local pathvar=${2:-PATH}                                                       
  for dir in ${!pathvar} ; do                                                    
    if [ "$dir" != "$1" ] ; then                                                 
      newpath=${newpath:+$newpath:}$dir                                          
    fi                                                                           
  done                                                                           
  export $pathvar="$newpath"                                                        
}

pathprepend () {                                                                 
  pathrm $1 $2                                                                   
  local pathvar=${2:-PATH}                                                       
  export $pathvar="$1${!pathvar:+:${!pathvar}}"                                  
}

pathappend () {                                                                    
  pathrm $1 $2                                                                   
  local pathvar=${2:-PATH}                                                       
  export $pathvar="${!pathvar:+${!pathvar}:}$1"                                  
} 

La plupart des autres solutions proposées reposent uniquement sur la correspondance de chaîne et ne prennent pas en compte les segments de chemin contenant des noms spéciaux comme ., .. ou ~. La fonction bash ci-dessous résout les chaînes de répertoire dans son argumentation et dans les segments de chemin pour trouver le répertoire logique correspond ainsi que les correspondances.

rm_from_path() {
  pattern="${1}"
  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'

Linux à partir de zéro définit trois fonctions bash /etc/profile:

# Functions to help us manage paths.  Second argument is the name of the
# path variable to be modified (default: PATH)
pathremove () {
        local IFS=':'
        local NEWPATH
        local DIR
        local PATHVARIABLE=${2:-PATH}
        for DIR in ${!PATHVARIABLE} ; do
                if [ "$DIR" != "$1" ] ; then
                  NEWPATH=${NEWPATH:+$NEWPATH:}$DIR
                fi
        done
        export $PATHVARIABLE="$NEWPATH"
}

pathprepend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="$1${!PATHVARIABLE:+:${!PATHVARIABLE}}"
}

pathappend () {
        pathremove $1 $2
        local PATHVARIABLE=${2:-PATH}
        export $PATHVARIABLE="${!PATHVARIABLE:+${!PATHVARIABLE}:}$1"
}

export -f pathremove pathprepend pathappend

Ref: http://www.linuxfromscratch.org/blfs/ vue / svn / postlfs / profile.html

J'aime les trois fonctions indiquées dans @ la mise à jour de BenBlank à sa question initiale. Pour les généraliser, j'utiliser un formulaire 2 argument, ce qui me permet de définir PATH ou toute autre variable d'environnement que je veux:

path_append ()  { path_remove $1 $2; export $1="${!1}:$2"; }
path_prepend () { path_remove $1 $2; export $1="$2:${!1}"; }
path_remove ()  { export $1="`echo -n ${!1} | awk -v RS=: -v ORS=: '$1 != "'$2'"' | 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 approprié des espaces contenant des noms de fichiers.

Depuis cela tend à être très problématique, comme il n'y a pas de façon élégante, je vous recommande d'éviter le problème en réorganisant la solution. Construire votre PATH plutôt que de tenter de le détruire

Je pourrais être plus précis si je savais que votre contexte réel problème. Dans l'intervalle, je vais utiliser une version du logiciel est le contexte.

Un problème commun avec le logiciel construit est qu'il casse sur certaines machines, en fin de compte en raison de la façon dont quelqu'un a configuré sa shell par défaut (PATH et d'autres variables d'environnement). La solution élégante est de rendre vos scripts construire immunitaire en spécifiant complètement l'environnement du shell. Code vos scripts de compilation pour définir le chemin et d'autres variables d'environnement basé sur l'assemblage des pièces que vous contrôlez, comme l'emplacement du compilateur, des bibliothèques, des outils, des composants, etc. Chaque élément doit être configuré quelque chose que vous pouvez définir individuellement, vérifiez et puis utiliser de façon appropriée dans votre script.

Par exemple, j'ai une version Java WebLogic ciblée basée sur Maven que j'ai hérité de mon nouvel employeur. Le script de construction est connu pour être fragile, et un autre nouvel employé et j'ai passé trois semaines (temps plein, juste ici et là, mais encore beaucoup d'heures) le faire fonctionner sur nos machines. Une étape essentielle est que je pris le contrôle du chemin afin que je savais exactement où Java, Maven, et qui WebLogic a été invoquée. J'ai créé des variables d'environnement pour pointer vers chacun de ces outils, je calcule le PATH basé sur les plus quelques autres. Des techniques similaires domptés les autres paramètres configurables, jusqu'à ce que nous a finalement créé une version reproductible.

Par ailleurs, ne pas utiliser Maven, Java est correct, et seulement acheter WebLogic si vous avez absolument besoin de son regroupement (mais sinon pas, et surtout pas ses caractéristiques exclusives).

Les meilleurs voeux.

Comme @litb, je contribuais une réponse à la question " Comment garder de duplication variable PATH csh ».

Ce qui rend ce problème ennuyeux sont les cas de fencepost entre premier et dernier éléments. Le problème peut être résolu avec élégance en changeant IFS et en utilisant un tableau, mais je ne sais pas comment réintroduire le côlon une fois que le chemin est converti sous forme de tableau.

Voici une version légèrement moins élégante qui supprime un répertoire de manipulation en utilisant uniquement $PATH de chaîne. Je l'ai testé.

#!/bin/bash
#
#   remove_from_path dirname
#
#   removes $1 from user's $PATH

if [ $# -ne 1 ]; then
  echo "Usage: $0 pathname" 1>&2; exit 1;
fi

delendum="$1"
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 un Perl one-liner:

PATH=`perl -e '$a=shift;$_=$ENV{PATH};s#:$a(:)|^$a:|:$a$#$1#;print' /home/usr/bin`

La variable obtient le chemin $a à enlever. Le s (suppléant) et print commandes opèrent implicitement sur la variable $_.

Une bonne adresse ici. Je l'utilise celui-ci pour ne pas ajouter 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 jokers 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 englobement d'un revêtement (ainsi, en quelque sorte):

path_remove ()  { shopt -s extglob; PATH="${PATH//+(${1})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 

Il ne semble pas nécessaire d'échapper à barres obliques dans 1 $.

path_remove ()  { shopt -s extglob; declare escArg="${1//\//\\/}"; PATH="${PATH//+(${escArg})+([^:])?(:)/}"; export PATH="${PATH%:}"; shopt -u extglob; return 0; } 

Ajout de chemin que nous côlons 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 vieux, je pensais 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 cette . Je pense que j'aime ce un plus:)

Je pris une approche légèrement différente que la plupart des gens ici et concentrais spécifiquement sur seulement la manipulation de chaînes, comme suit:

path_remove () {
    if [[ ":$PATH:" == *":$1:"* ]]; then
        local dirs=":$PATH:"
        dirs=${dirs/:$1:/:}
        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éé et path_add_before vous permettant d'insérer path_add_after un chemin avant / après un chemin d'accès spécifié déjà PATH.

L'ensemble des fonctions disponibles dans path_helpers.sh dans mon dotfiles . Ils soutiennent pleinement la suppression / appending / appending / insertion au début / milieu / fin de la chaîne PATH.

La fuite « : » est causé par le fait que vous définissez la fin de la ligne, pas le séparateur. J'utilise des unités limitted de ressources et, comme pour emballer le tout dans un seul script, sans ces bizarreries:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top