Pregunta

O, de manera más general, ¿cómo elimino un elemento de una lista separada por dos puntos en una variable de entorno Bash?

Pensé que había visto una forma sencilla de hacer esto hace años, usando las formas más avanzadas de expansión de variables de Bash, pero si es así, le perdí la pista.Una búsqueda rápida en Google arrojó sorprendentemente pocos resultados relevantes y ninguno que yo llamaría "simple" o "elegante".Por ejemplo, dos métodos usan sed y awk respectivamente:

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)

¿No existe nada sencillo?¿Hay algo análogo a una función split() en Bash?

Actualizar:
Parece que necesito disculparme por mi pregunta intencionalmente vaga;Estaba menos interesado en resolver un caso de uso específico que en provocar una buena discusión.¡Afortunadamente lo conseguí!

Aquí hay algunas técnicas muy inteligentes.Al final, agregué las siguientes tres funciones a mi caja de herramientas.La magia ocurre en path_remove, que se basa en gran medida en el uso inteligente que hace Martin York de awkLa variable RS.

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

El único problema real es el uso de sed para eliminar los dos puntos finales.Sin embargo, considerando lo sencillo que es el resto de la solución de Martin, ¡estoy dispuesto a vivir con ella!


Pregunta relacionada: ¿Cómo manipulo elementos $PATH en scripts de shell?

¿Fue útil?

Solución

A minutos con awk:

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

Edit: respuesta a las observaciones siguientes:

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

Editar en respuesta al problema de la seguridad: (que no es relevante para la cuestión)

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

Esto elimina cualquier dos puntos se arrastran de la izquierda mediante la supresión de las últimas entradas, lo que efectivamente añadir . a su ruta.

Otros consejos

Mi truco sucio:

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

Desde el gran problema con la sustitución es los casos extremos, la forma de hacer los casos extremos que no son diferentes a los otros casos? Si la ruta ya tenía dos puntos al principio y al final, podríamos simplemente buscar nuestra cadena deseada envuelto con dos puntos. Como es, podemos añadir fácilmente esos dos puntos y eliminarlos despué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

fiesta pura:.)

Esta es la solución más simple que puedo concebir:

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

El ejemplo anterior se eliminará cualquier elemento en $ PATH que contiene "usr". Puede reemplazar "* * usr" con "/ home / usuario / bin" para eliminar sólo ese elemento.

actualización sschuberth

A pesar de que creo espacios en un $PATH son una horribles idea, he aquí una solución que lo maneja:

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

Aquí hay una sola línea que, a pesar de la actual aceptado y respuestas de más alto rating , no añada caracteres invisibles a PATH y puede hacer frente a rutas que contienen espacios:

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

En lo personal, me parece también esta fácil de leer / entender, y que sólo involucra a los comandos comunes en vez de usar awk.

Esta es una solución que:

  • Bash es puro,
  • no invocar otros procesos (como 'sed' o 'awk'),
  • no cambia IFS,
  • no bifurcar un sub-shell,
  • maneja caminos con espacios, y
  • elimina todas las apariciones del argumento en PATH.

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

Función __path_remove () {
     Local D = ": $ {PATH}:";
     [ "$ {D /: $ 1: /:}" = "$ D"!] && PATH = "$ {D /: $ 1: /:}";
     PATH = "$ {PATH / #: /}";
     Export PATH = "$ {PATH /%: /}";
  }

lo sacó de mi archivo .bashrc. Al jugar con PATH, y se pierde, awk / sed / grep deja de estar disponible: -)

La mejor opción fiesta pura que he encontrado hasta ahora es la siguiente:

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
}

Esto se basa en la no respuesta del todo correcto a Añadir directorio para $ PATH si no está ya allí sobre el superusuario.

He estado usando las funciones en la distribución bash, que aparentemente han estado ahí desde 1991.Estos todavía están en el paquete bash-docs en Fedora y solían usarse en /etc/profile, pero no más...

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

he escrito una respuesta a esta aquí (usando awk también). Pero no estoy seguro de que eso es lo que busca? Por lo menos, parece claro para mí lo que hace, en lugar de tratar de encajar en una sola línea. Para un simple chiste, sin embargo, que sólo elimina la materia, lo recomiendo

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

Sustitución es

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

o (más corto, pero menos legible)

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

De todos modos, para la misma pregunta, y una gran cantidad de respuestas útiles, v aquí .

Bueno, en bash, ya que soporta expresiones regulares, yo simplemente hacer:

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

¿Cuál es la forma más elegante para eliminar un camino desde la variable $ PATH en Bash?

Lo que es más elegante que awk?

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

Python! Es una solución más legible y fácil de mantener, y es fácil de inspeccionar para ver que realmente está haciendo lo que quiere.

Supongamos que desea quitar el primer elemento de la ruta?

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

(En lugar de tuberías de echo, os.getenv['PATH'] sería un poco más corto, y siempre que el mismo resultado que el anterior, pero me preocupa que Python podría hacer algo con esa variable de entorno, por lo que es probable que sea mejor tubería directamente desde el entorno que le interesan.)

Del mismo modo para eliminar desde el extremo:

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

Para realizar estas funciones de shell reutilizables que se puede, por ejemplo, se adhieren en su archivo .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))")"
}

Sí, poniendo dos puntos al final de PATH, por ejemplo, hace que la eliminación de un camino un poco menos torpe y propenso a errores.

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 usted está preocupado por la eliminación de duplicados en $ PATH, la forma más elegante, en mi humilde opinión, sería no añadirlos en el primer lugar. En 1 línea:

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

carpeta $ puede ser sustituido por cualquier cosa, y puede contener espacios ( "/ home / usuario / mis documentos")

La solución más elegante pura fiesta que he encontrado hasta la fecha:

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 mayoría de las otras soluciones propuestas se basan únicamente en la coincidencia de cadenas y no toman en cuenta los segmentos de trazado que contienen nombres especiales como ., .. o ~. La función de golpe por debajo resuelve cadenas de directorio en su argumento y en los segmentos de trazado para encontrar directorio lógico coincide, así como partidos de cuerda.

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

Prueba:

$ 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 desde cero define tres funciones de Bash en /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/ ver / svn / postlfs / profile.html

Me gustan las tres funciones que se muestran en la actualización de BenBlank @ a su pregunta original. Generalizarlos, utilizo una forma 2-argumento, lo que me permite establecer la ruta o cualquier otra variable de entorno que quiero:

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

Ejemplos de uso:

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

Tenga en cuenta que también añadí algunos comillas para permitir el procesamiento adecuado de las rutas de acceso que contienen espacios.

Dado que esto tiende a ser bastante problemático, ya que NO HAY una manera elegante, recomiendo evitar el problema reorganizando la solución:construye tu RUTA en lugar de intentar derribarla.

Podría ser más específico si conociera el contexto real del problema.Mientras tanto, utilizaré una compilación de software como contexto.

Un problema común con las compilaciones de software es que falla en algunas máquinas, en última instancia debido a cómo alguien configuró su shell predeterminado (PATH y otras variables de entorno).La solución elegante es hacer que sus scripts de compilación sean inmunes especificando completamente el entorno del shell.Codifique sus scripts de compilación para establecer la RUTA y otras variables de entorno en función del ensamblaje de piezas que usted controla, como la ubicación del compilador, bibliotecas, herramientas, componentes, etc.Haga de cada elemento configurable algo que pueda configurar, verificar y luego usar de forma individual en su secuencia de comandos.

Por ejemplo, tengo una compilación Java orientada a WebLogic basada en Maven que heredé de mi nuevo empleador.El script de compilación es conocido por ser frágil, y otro empleado nuevo y yo pasamos tres semanas (no a tiempo completo, solo aquí y allá, pero sí muchas horas) para que funcione en nuestras máquinas.Un paso esencial fue tomar el control de PATH para saber exactamente qué Java, qué Maven y qué WebLogic se estaba invocando.Creé variables de entorno para apuntar a cada una de esas herramientas, luego calculé la RUTA en función de esas y algunas otras.Técnicas similares controlaron las otras configuraciones configurables, hasta que finalmente creamos una compilación reproducible.

Por cierto, no use Maven, Java está bien y solo compre WebLogic si es absolutamente necesario su agrupación en clústeres (pero por lo demás no, y especialmente no sus características patentadas).

Los mejores deseos.

Al igual que @litb, contribuí con una respuesta a la pregunta "¿Cómo manipulo elementos $PATH en scripts de shell?", entonces mi respuesta principal está ahí.

La funcionalidad 'dividir' en bash y otros derivados de Bourne Shell se logra mejor con $IFS, el separador entre campos.Por ejemplo, para establecer los argumentos posicionales ($1, $2, ...) a los elementos de PATH, use:

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

Funcionará bien siempre que no haya espacios en $PATH.Hacer que funcione para elementos de ruta que contienen espacios no es un ejercicio trivial que se deja para el lector interesado.Probablemente sea más sencillo solucionarlo utilizando un lenguaje de programación como Perl.

También tengo un guión clnpath, que uso mucho para configurar mi RUTA.Lo documenté en la respuesta a "Cómo evitar duplicar la variable PATH en csh".

Lo que hace que este molesto problema son los casos de Fencepost entre los elementos primero y el último. El problema puede ser resuelto elegantemente cambiando IFS y el uso de una matriz, pero no sé cómo volver a introducir el colon una vez que el camino se convierte en forma de matriz.

Esta es una versión ligeramente menos elegante que elimina un directorio de $PATH utilizando sólo la manipulación de cadenas. He probado.

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

Aquí está un Perl de una sola línea:

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

El $a variable obtiene el camino para ser eliminado. El s (sustituto) y print comandos implícitamente operan en la $_ variable.

Eso está muy bien aquí. Yo uso este para evitar la adición de duplicados en el primer lugar.

#!/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 el englobamiento extendido permitió que es posible hacer lo siguiente:

# 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

englobamiento extendido de una sola línea (bueno, casi):

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

Parece que no hay necesidad de escapar de barras en $ 1.

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

La adición de dos puntos al PATH también podríamos hacer algo como:

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 

En path_remove_all (por proxxy):

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

Si bien este es un hilo muy antiguo, pensé que esta solución podría ser de interés:

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

encontró en este href="http://unstableme.blogspot.com/2009/05/remove-path-from-path-variable-in-bash.html" entrada de blog . Creo que me gusta más ésta:)

Adopté un enfoque ligeramente diferente al de la mayoría de las personas aquí y me centré específicamente en la manipulación de cadenas, así:

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

Lo anterior es un ejemplo simplificado de las funciones finales que utilizo.yo también he creado path_add_before y path_add_after permitiéndole insertar una ruta antes/después de una ruta especificada que ya está en PATH.

El conjunto completo de funciones está disponible en ruta_helpers.sh en mi archivos de puntos.Son totalmente compatibles con eliminar/añadir/anteponer/insertar al principio/medio/final de la cadena PATH.

El terminador ':' es causada por el hecho de que se está ajustando el final de línea, no el separador. Yo uso limitted unidades de recursos y como para empacar todo en una única secuencia de comandos, sin estas rarezas:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top