Domanda

O, più in generale, come faccio a rimuovere un elemento da un colon-elenco separato in un ambiente Bash variabile?

Pensavo di aver visto un modo semplice per farlo anni fa, utilizzando le forme più avanzate di Bash espansione di una variabile, ma se è così ho perso traccia.Una veloce ricerca in Google alzato sorprendentemente pochi risultati importanti e nessuno che io chiamerei "semplice" o "elegante".Per esempio, due metodi di utilizzo di sed e awk, rispettivamente:

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)

Non fa nulla semplice esistere?C'è qualcosa di analogo a una split() funzione in Bash?

Aggiornamento:
Sembra che ho bisogno di scusarmi per la mia intenzionalmente vago domanda;Ero meno interessato a risolvere un caso d'uso che nello sviluppo di una buona discussione.Per fortuna, l'ho preso!

Ci sono alcune tecniche intelligenti qui.Alla fine, ho aggiunto i seguenti tre funzioni per la mia casella degli strumenti.La magia accade in path_remove, che si basa in gran parte su Martin York sapiente uso di awk's RS variabile.

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/:$//'`; }

L'unica vera spazzatura è l'uso di sed rimuovere i due punti finali.Considerando come semplice è il resto di Martin soluzione è, comunque, sono abbastanza disposti a vivere con lui!


Domanda correlata: Come faccio a manipolare $elementi di un PERCORSO in script di shell?

È stato utile?

Soluzione

Un minuto con awk:

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

Modifica: E 'risposta a commenti qui sotto:

$ 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!

Modifica in risposta al problema della sicurezza: (che non è rilevante per la domanda)

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

Questo rimuove ogni due punti di trascinamento sinistra cancellando le ultime voci, il che potrebbe effettivamente aggiungere . al percorso.

Altri suggerimenti

Il mio sporco trucco:

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

Dal momento che il grosso problema con la sostituzione è nei casi terminali, che ne dici di fare i casi di fine non è diverso da altri casi? Se il percorso già avuto due punti all'inizio e alla fine, potremmo semplicemente cercare la nostra stringa desiderata avvolto con i due punti. Così com'è, possiamo facilmente aggiungere questi due punti e rimuoverli in seguito.

# 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 Pure:.)

Ecco la soluzione più semplice che posso inventare:

#!/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'esempio precedente consente di eliminare ogni elemento in $ PATH che contiene "usr". È possibile sostituire "* * usr" con "/ home / user / bin" per rimuovere proprio questo elemento.

Aggiorna per sschuberth

Anche se penso che gli spazi in un $PATH sono un orribile idea, ecco una soluzione che gestisce:

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[*]}");

o

IFS=':'
t=($PATH)
n=${#t[*]}
a=()
for ((i=0;i<n;i++)); do
  p="${t[i]%%*usr*}"
  [ "${p}" ] && a[i]="${p}"
done
echo "${a[*]}"

Ecco un one-liner che, nonostante l'attuale accettato e risposte più votati , non aggiunge caratteri invisibili al PATH e in grado di far fronte con i percorsi che contengono spazi:

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

Personalmente, trovo anche questo di facile lettura / capire, e coinvolge solo i comandi comuni invece di usare awk.

Ecco una soluzione che:

  • è Bash puro,
  • non invocare altri processi (come 'sed' o 'awk'),
  • non cambia IFS,
  • non fork di un sub-shell,
  • gestisce i percorsi con spazi, e
  • rimuove tutte le occorrenze della argomento a PATH.

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

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

Dug fuori dal mio file .bashrc. Quando si gioca in giro con PATH, e si perde, awk / sed / grep non è più disponibile: -)

L'opzione migliore pura bash che ho trovato finora è la seguente:

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
}

Questa è basata sul non del tutto corretta risposta per Aggiungi directory a $ PATH se non è già presente oltre Superuser.

Ho appena usato le funzioni nella distribuzione bash, che a quanto pare sono stati lì dal 1991. Questi sono ancora nel pacchetto bash-docs su Fedora, e utilizzati per essere utilizzato in /etc/profile, ma non di più. ..

$ 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;:\$;;"`
}

ho scritto una risposta a questo qui (utilizzando awk troppo). Ma io non sono sicuro che è quello che stai cercando? E 'di almeno sembra chiaro per me quello che fa, invece di cercare di inserirsi in una sola riga. Per un semplice uno di linea, però, che rimuove solo roba, mi raccomando

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

La sostituzione è

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

o (più breve, ma meno leggibile)

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

In ogni caso, per la stessa domanda, e un sacco di risposte utili, vedere qui .

Bene, in bash, in quanto supporta espressioni regolari, vorrei semplicemente fare:

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

Qual è il modo più elegante per rimuovere un percorso dalla variabile $ PATH in Bash?

Cosa c'è di più elegante di awk?

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

Python! Si tratta di una soluzione più leggibile e gestibile, ed è facilmente ispezionabile per vedere che è davvero fare quello che vuoi.

Dire che si desidera rimuovere il primo elemento del percorso?

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

(Invece di tubazioni da echo, os.getenv['PATH'] sarebbe un po 'più corto, e ha fornito lo stesso risultato di cui sopra, ma sono preoccupato che Python potrebbe fare qualcosa con quella variabile d'ambiente, quindi è probabilmente meglio pipe direttamente dall'ambiente che ti interessano.)

Allo stesso modo per rimuovere dalla fine:

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

Per rendere queste funzioni di shell riutilizzabili che è possibile, per esempio, il bastone nel file .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))")"
}

Si, mettendo i due punti alla fine del percorso, ad esempio, rende la rimozione di un percorso un po 'meno impacciato e soggetto a errori.

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 

Se siete preoccupati per la rimozione di duplicati in $ PATH, il modo più elegante, secondo me, sarebbe di non aggiungere loro in primo luogo. In 1 riga:

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

$ può essere essere sostituita da niente, e può contenere spazi ( "/ home / utente / i miei documenti")

La soluzione bash pura più elegante che ho trovato fino ad oggi:

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 maggior parte delle altre soluzioni proposte si basano solo su string matching e non tengono conto segmenti di percorso che contengono nomi speciali come ., .. o ~. La funzione di bash di seguito risolve stringhe di directory nel suo argomento ed in segmenti di percorso per trovare directory logica corrisponde così come le partite di stringa.

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}
}

Prova:

$ 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 From Scratch definisce tre funzioni di Bash in /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

Rif: http://www.linuxfromscratch.org/blfs/ view / svn / postlfs / profile.html

Mi piacciono le tre funzioni mostrate in @ aggiornamento di BenBlank alla sua domanda iniziale. Per generalizzare loro, io uso un modulo 2-argomento, che mi permette di impostare il percorso o di qualsiasi altra variabile d'ambiente che voglio:

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/:$//'`"; }

Esempi di utilizzo:

path_prepend PATH /usr/local/bin
path_append PERL5LIB "$DEVELOPMENT_HOME/p5/src/perlmods"

Si noti che ho anche aggiunto alcuni virgolette per consentire il corretto trattamento dei percorsi che contengono spazi.

Dal momento che questo tende ad essere abbastanza problematico, come in Non c'è modo elegante, vi consiglio di evitare il problema riorganizzando la soluzione:. Costruire il vostro PATH up, piuttosto che tentare di abbatterlo

potrei essere più preciso se sapevo vostro contesto vero problema. Nel frattempo, userò una configurazione software a seconda del contesto.

Un problema comune con il software si basa è che si rompe su alcune macchine, in ultima analisi, a causa di come qualcuno ha configurato la shell di default (PATH e altre variabili d'ambiente). La soluzione elegante è quello di rendere i vostri script di build immunitario specificando appieno l'ambiente di shell. Codice tuoi script di build per impostare le variabili PATH e altro ambiente basate sulle assemblando pezzi che si controlla, come ad esempio la posizione del compilatore, biblioteche, strumenti, componenti, ecc rendono ogni articolo qualcosa configurabile che è possibile impostare individualmente, verificare, e quindi utilizzare in modo appropriato nello script.

Per esempio, ho una generazione Java WebLogic mirato Maven-based che ho ereditato il mio nuovo datore di lavoro. Lo script di build è noto per essere fragili, e un altro nuovo dipendente e ho trascorso tre settimane (non a tempo pieno, solo qua e là, ma ancora molte ore) ottenendo di lavorare sulle nostre macchine. Un passo essenziale è che ho preso il controllo del percorso in modo che sapevo esattamente quali Java, che Maven, e che WebLogic veniva invocata. Ho creato le variabili di ambiente per puntare a ciascuno di questi strumenti, quindi ho calcolato il PATH sulla base di quelli più alcuni altri. Tecniche simili domato le altre impostazioni configurabili, fino a quando abbiamo finalmente creato un accumulo riproducibile.

A proposito, non utilizzare Maven, Java è a posto, e solo comprare WebLogic se è assolutamente necessario il suo raggruppamento (ma per il resto no, e soprattutto non le sue caratteristiche proprietarie).

I migliori auguri.

Come con @litb, ho contribuito una risposta alla domanda "Come faccio a manipolare $elementi di un PERCORSO in script di shell", quindi la mia risposta è lì.

La "suddivisione" funzionalità bash e altri Bourne shell derivati è più ordinatamente raggiunto con $IFS, inter-separatore di campo.Per esempio, per impostare gli argomenti posizionali ($1, $2, ...) per gli elementi di PERCORSO, utilizzare:

set -- $(IFS=":"; echo "$PATH")

Funziona bene fino a quando non ci sono spazi in $PATH.Farlo funzionare per gli elementi di percorso contiene spazi non è un esercizio banale - sinistra per il lettore interessato.È probabilmente più semplice di trattare con esso utilizzando un linguaggio di scripting come Perl.

Anche io ho uno script, clnpath, che io uso ampiamente per la regolazione del mio PERCORSO.Mi sono documentato in risposta a "Come evitare di duplicare variabile PATH in csh".

Ciò che rende questo fastidioso problema sono i casi fencepost tra primo e l'ultimo elemento. Il problema può essere risolto modificando elegantemente IFS e utilizzando una matrice, ma non so come reintrodurre il colon quando il percorso viene convertito in forma di matrice.

Ecco una versione leggermente meno elegante che rimuove una directory dalla $PATH utilizzando solo la manipolazione delle stringhe. Ho testato.

#!/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"

Ecco un Perl one-liner:

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

Il $a variabile ottiene il percorso da rimuovere. Il s (sostituto) e print comandi implicitamente operano sul $_ variabile.

Buona roba qui. Io uso questo per evitare di aggiungere dupes in primo luogo.

#!/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

Con globbing esteso abilitati è possibile effettuare le seguenti operazioni:

# 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

globbing esteso one-liner (beh, quasi):

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

Non sembra esserci bisogno di fuggire barre in $ 1.

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

L'aggiunta di due punti al PATH potremmo anche fare qualcosa di simile:

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 

In path_remove_all (da proxxy):

-newPATH="${newPATH//:+(${@:${i}:1})*([^:])/}" 
+newPATH="${newPATH//:${@:${i}:1}*([^:])/}"        # s/:\/path[^:]*//g 

Anche se questo è un filo molto vecchio, ho pensato che questa soluzione potrebbe essere di interesse:

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

trovato in questo post sul blog . Penso che mi piace questo uno più:)

Ho preso un approccio leggermente diverso rispetto alla maggior parte di persone qui e si concentra in particolare sul proprio manipolazione delle stringhe, in questo modo:

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#?}
}

Quanto sopra è un esempio semplificato delle funzioni finali che uso. Ho anche creato path_add_before e path_add_after permettendo si inserisce un percorso prima / dopo un percorso specificato già in PATH.

Il set completo di funzioni sono disponibili in path_helpers.sh nel mio dotfile . Essi supportano completamente rimozione / apposizione / prepending / inserimento a inizio / metà / fine della stringa PATH.

Il finale ':' è causato dal fatto che si sta impostando il finale di linea, non il separatore. Io uso di risorse unità limitted e piace mettere in valigia tutto in un singolo script, senza queste stranezze:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top