Frage

Oder allgemeine, wie entferne ich ein Element aus einem Doppelpunkt getrennte Liste in einem Bash-Umgebungsvariable?

Ich dachte, ich hätte eine einfache Art und Weise gesehen vor Jahren zu tun, die fortgeschrittenen Formen der Bash variable Expansion verwenden, aber wenn so habe ich Spur davon verloren. Eine schnelle Suche von Google drehte überraschend wenige relevante Ergebnisse und keine, die ich „einfache“ oder „elegant“ nennen. Zum Beispiel können zwei Methoden sed und awk mit jeweils:

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)

Gibt es nichts einfach exist? Gibt es etwas, analog zu einer split () Funktion in Bash?

Update:
Es sieht aus wie ich für meine absichtlich vage Frage entschuldigen müssen; Ich war weniger daran interessiert, einen spezifischen Anwendungsfall als zu provozieren gute Diskussion zu lösen. Glücklicherweise habe ich es!

Es gibt einige sehr clevere Techniken hier. Am Ende habe ich die folgenden drei Funktionen zu meinem Werkzeugkasten hinzugefügt. Die Magie geschieht in path_remove, die auf Martin York geschickten Einsatz von awk RS Variable weitgehend basiert.

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

Die einzige wirkliche cruft dort ist die Verwendung von sed den hinteren Doppelpunkt zu entfernen. Bedenkt man, wie einfach der Rest von Martins Lösung ist, bin ich jedoch durchaus bereit, mit ihm zu leben!


Verwandte Frage: How ich $ PATH Elemente in Shell-Skripten zu manipulieren?

War es hilfreich?

Lösung

Eine Minute mit awk:

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

Edit: Es Reaktion auf die Kommentare unter:

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

Edit als Antwort auf Sicherheitsproblem: (das ist die Frage nicht relevant)

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

Dies entfernt alle Hinter Doppelpunkten links durch die letzten Einträge zu löschen, die effektiv . zu Ihrem Pfad hinzufügen würde.

Andere Tipps

Meine schmutzige Hack:

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

Da das große Problem mit Substitution ist die End-Fälle, wie etwa die Herstellung der End-Fälle nicht anders zu den anderen Fällen? Wenn der Pfad bereits Doppelpunkte am Anfang und Ende hat, konnten wir einfach für unsere gewünschte Zeichenfolge mit Doppelpunkten gewickelt suchen. Wie es ist, können wir leicht diese Doppelpunkte hinzufügen und entfernen Sie sie danach.

# 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

Reine bash:.)

Hier ist die einfachste Lösung, die ich entwickeln kann:

#!/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[*]}"

Das obige Beispiel wird jedes Element in $ PATH entfernen, die "usr" enthält. Sie können ersetzen "* usr *" mit "/ home / user / bin" gerade dieses Element zu entfernen.

Update sschuberth

Auch wenn ich denke, dass Räume in einem $PATH sind eine schrecklich Idee, hier ist eine Lösung, die es behandelt:

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

oder

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

Hier ist ein Einzeiler, dass trotz der aktuellen akzeptiert und Antworten bestbewertesten, fügen Sie nicht unsichtbare Zeichen auf PATH und können mit Pfaden bewältigen, die Leerzeichen enthalten:

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

Persönlich finde ich auch diese leicht / verstehen zu lesen, und es handelt sich nur um allgemeine Befehle anstelle von awk.

Hier ist eine Lösung, die:

  • ist reine Bash,
  • keine anderen Prozesse aufrufen (wie 'sed' oder 'awk')
  • nicht IFS ändern,
  • Gabel keine Unterschale,
  • Griffe Pfade mit Leerzeichen und
  • entfernt alle Vorkommen des Arguments in PATH.

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

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

Dug es von meinem .bashrc aus. Wenn Sie mit PATH spielen, um, und es geht verloren, awk / sed / grep nicht mehr verfügbar ist: -)

Die beste reine bash Option, die ich gefunden habe, so weit ist wie folgt vor:

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
}

Dies basiert auf der nicht ganz richtige Antwort Fügen sie Verzeichnis $ PATH, wenn es nicht bereits vorhanden ist über auf Superuser.

Ich habe gerade die Funktionen in der Bash-Verteilung unter Verwendung von, dass es offenbar gewesen seit 1991 auf Fedora Diese sind immer noch in dem Bash-Docs-Paket, und verwendete, um in /etc/profile verwendet werden, aber nicht mehr ...

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

Ich habe hier eine Antwort auf diese schreiben (mit awk auch). Aber ich bin nicht sicher, dass das, was Sie suchen? Es zumindest sieht mir klar, was es tut, anstatt zu versuchen, in eine Zeile zu passen. Für eine einfache Auskleidung ein, aber, dass nur entfernt material, ich empfehlen

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

zu ersetzen, ist

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

oder (kürzer, aber weniger lesbar)

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

Wie auch immer, für die gleiche Frage, und eine ganze Menge nützlicher Antworten finden Sie unter hier .

Nun, in bash, wie es für reguläre Ausdrücke unterstützt, würde ich einfach tun:

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

Was ist die eleganteste Art und Weise einen Weg von dem $ PATH-Variable in Bash zu entfernen?

Was als awk elegantere ist?

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

Python! Es ist eine lesbare und wartbare Lösung, und es ist leicht zu sehen, zu prüfen, dass es wirklich tut, was Sie wollen.

Sagen Sie den ersten Weg Element entfernen?

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

(Anstelle von Rohrleitungen aus echo würde os.getenv['PATH'] etwas kürzer sein, und sofern das gleiche Ergebnis wie oben, aber ich mache mir Sorgen, dass Python könnte mit dieser Umgebungsvariable etwas tun, so ist es wahrscheinlich am besten, Rohr direkt aus die Umgebung, die Sie kümmern uns um.)

Ebenso vom Ende zu entfernen:

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

Um diese wieder verwendbaren Shell-Funktionen, die Sie können zum Beispiel Stick in Ihrer .bashrc-Datei:

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

Ja, am Ende der PATH einen Doppelpunkt setzt zum Beispiel macht einen Weg ein bisschen weniger plump und fehleranfällig zu entfernen.

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 

Wenn Sie besorgt sind über das Entfernen von Duplikaten in $ PATH, der eleganteste Weg, IMHO, wäre sie nicht in erster Linie hinzuzufügen. In 1 Zeile:

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

$ Ordner durch nichts ersetzt werden kann und Leerzeichen enthalten können ( "/ home / user / meine Dokumente")

Die eleganteste reine bash Lösung, die ich bisher gefunden habe:

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

Die meisten anderen vorgeschlagenen Lösungen beruhen nur auf String-Matching und sie berücksichtigen nicht die Pfadsegmente mit speziellen Namen wie ., .. oder ~. Die Bash-Funktion löst unter Verzeichnis Strings in ihrer Argumentation und in Pfadsegmente logisch zu suchen Spiele sowie Zeichenfolge entspricht.

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 from Scratch definiert drei Bash-Funktionen 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

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

Ich mag die drei gezeigten Funktionen in @ BenBlank das Update auf seine ursprüngliche Frage. Verallgemeinert sie, verwende ich eine 2-Argument Form, die ich PATH oder andere Umgebungsvariable festlegen kann Ich möchte:

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

Anwendungsbeispiele:

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

Beachten Sie, dass ich auch einige Anführungszeichen hinzugefügt für die ordnungsgemäße Verarbeitung von Pfadnamen zu ermöglichen, die Leerzeichen enthalten.

Da dies jedoch häufig sehr problematisch zu sein, da dort keine elegante Art und Weise, ich empfehlen, das Problem zu vermeiden, indem die Lösung neu anordnen. Bauen Sie Ihren PATH oben anstatt zu versuchen, es abzureißen

Ich könnte sein, spezifischere, wenn ich Ihren eigentliches Problem Kontext weiß. In der Zwischenzeit werde ich einen Software-Build als Kontext verwendet werden.

Ein häufiges Problem mit Software baut ist, dass es auf einigen Maschinen bricht schließlich durch, wie jemand ihre Standard-Shell (PATH und andere Umgebungsvariablen) konfiguriert hat. Die elegante Lösung ist Ihr Build-Skripte Immun durch vollständig unter Angabe der Shell-Umgebung zu machen. Code Ihres Build-Skripte, die PATH und andere Umgebungsvariablen auf Montag Stücke auf der Basis einstellen, die Sie, wie die Lage der Compiler, Bibliotheken, Werkzeuge, Komponenten zu steuern, etc. Stellen jedes konfigurierbare Element etwas, das Sie individuell einstellen kann, überprüfen und dann in geeigneter Weise in Ihrem Skript verwenden.

Zum Beispiel, ich habe eine Maven-basierte WebLogic-bezogene Java Build, die mich an meinem neuen Arbeitgeber geerbt. Der Build-Skript ist berüchtigt für zerbrechlich, und ein weiteren neue Mitarbeiter und ich verbrachten drei Wochen (nicht Vollzeit, nur hier und da, aber immer noch viele Stunden) bekommen es auf unseren Maschinen zu arbeiten. Ein wesentlicher Schritt war, dass ich die Kontrolle über die PATH nahm, so dass ich wusste genau, welche Java, die Maven und welche WebLogic aufgerufen wurde. Ich habe Umgebungsvariablen zu jedem dieser Tools zeigen, dann ich den Weg auf diejenigen plus ein paar andere Basis berechnet. Ähnliche Techniken gezähmt die anderen konfigurierbaren Einstellungen, bis wir endlich einen reproduzierbaren Build erstellt.

Durch die Art und Weise, verwendet Maven nicht, Java ist in Ordnung, und nur WebLogic kaufen, wenn Sie absolut sein Clustering müssen (aber sonst nicht, und schon gar nicht seine proprietären Funktionen).

Die besten Wünsche.

Wie bei @litb, ich trug eine Antwort auf die Frage " Wie kann ich $ PATH Elemente in Shell-Skripten manipulieren ", so meine Haupt Antwort gibt.

Die ‚aufgespalten‘ -Funktionalität in bash und anderen Derivate Bourne-Shell wird am ordentlich mit $IFS erreicht, den Interfeldtrennzeichen. Um zum Beispiel der Positionsargumente zu setzen ($1, $2, ...) zu den Elementen der PATH verwenden:

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

Es funktioniert OK, solange es keine Leerzeichen in $ PATH. So dass es für Pfadelemente arbeiten Räume enthält, ist eine nicht-triviale Übung - links für den interessierten Leser. Es ist wahrscheinlich einfacher zu handhaben es eine Skriptsprache wie Perl verwendet wird.

Ich habe auch ein Skript, clnpath, die ich für die Einstellung meiner PATH ausgiebig nutzen. Ich dokumentierte es in der Antwort auf „ Wie um zu verhindern, Duplizieren PATH-Variable in csh “.

Was dieses Problem ärgerlich macht, sind die fencepost Fälle unter den ersten und letzten Elemente. Das Problem elegant gelöst werden, indem IFS verändert und ein Array, aber ich weiß nicht, wie der Darm wieder einzuführen, sobald der Weg in Array-Form umgewandelt wird.

Hier ist eine etwas weniger elegante Version, die ein Verzeichnis von $PATH entfernt nur String-Manipulation verwendet. Ich habe es getestet.

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

Hier ist ein Perl-Einzeiler:

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

Die $a Variable erhält den Pfad entfernt werden. Die s (Ersatz) und print Befehle auf dem $_ Variable implizit arbeiten.

Good stuff hier. Ich benutze diesen von Zugabe von Duplikaten in erster Linie zu halten.

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

Mit einer erweiterten Globbing aktiviert ist es möglich, die folgendes zu tun:

# 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

Erweiterte Globbing Einzeiler (na ja, eine Art):

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

Das scheint nicht nötig zu entkommen Schrägstriche in $ 1.

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

Doppelpunkte zu PATH Hinzufügen wir auch etwas tun könnten, wie:

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 (von proxxy):

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

Dies ist zwar ein sehr alter Thread ist, dachte ich diese Lösung interessant sein könnte:

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

fand es auf dieser Blog-Post . Ich denke, Ich mag dieses am meisten:)

habe ich einen etwas anderen Ansatz als die meisten Menschen hier und fokussiert speziell auf nur String-Manipulation, etwa so:

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

Das oben ist ein vereinfachtes Beispiel der endgültigen Funktionen, die ich verwende. Ich habe auch path_add_before und path_add_after erstellt so dass Sie, bevor Sie einen Pfad einfügen / nach einem festgelegten Pfad bereits in PATH.

Der vollständige Satz von Funktionen zur Verfügung, in path_helpers.sh in meinem dotfiles . Sie voll unterstützt Entfernen / Anfügen / Prepending / Einfügen am Anfang / Mitte / Ende der PATH-Zeichenfolge.

Der Hinter ‚:‘ wird dadurch verursacht, dass Sie die Zeilenende setzen, nicht das Trennzeichen. Ich benutze Ressource limitted Einheiten und wie alles in ein einziges Skript zu packen, ohne diese Merkwürdigkeiten:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top