Pergunta

ou, mais geralmente, como faço para remover um item de uma lista separada por dois pontos em uma variável de ambiente Bash?

Eu pensei que tinha visto uma maneira simples de fazer isso anos atrás, usando as formas mais avançadas de expansão variável Bash, mas se assim for eu perdi o controle do mesmo. Uma rápida pesquisa do Google apareceu surpreendentemente poucos resultados e nenhum que eu chamaria de "simples" ou "elegante" relevantes. Por exemplo, os dois métodos com sed e 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)

exist nada simples faz? Existe análoga nada para uma função split () em Bash?

Update:
Parece que eu preciso pedir desculpas para o meu intencionalmente vago questão; Eu estava menos interessado em resolver um caso de uso específico do que em provocar boa discussão. Felizmente, eu consegui!

Existem algumas técnicas muito inteligente aqui. No final, eu adicionei os seguintes três funções à minha caixa de ferramentas. A mágica acontece em path_remove, que se baseia em grande parte no uso inteligente de Martin Iorque de variável 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/:$//'`; }

A única verdadeira cruft lá é o uso de sed para remover os dois pontos de fuga. Considerando o quão simples o resto da solução de Martin é, no entanto, estou bastante disposto a viver com ela!


questão relacionada: How faço para manipular $ elementos caminho no shell scripts?

Foi útil?

Solução

Um minuto com awk:

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

Edit: resposta aos comentários abaixo:

$ 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 em resposta ao problema de segurança: (que não é relevante para a questão)

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

Isso remove quaisquer dois pontos de arrasto deixadas pela exclusão do últimas entradas, o que efetivamente adicionar . ao seu caminho.

Outras dicas

Meu truque sujo:

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

Uma vez que o grande problema com a substituição é os casos finais, que tal fazer os casos finais há diferentes para os outros casos? Se o caminho já tinha dois pontos no início e no final, poderíamos simplesmente procurar a nossa seqüência desejada envolvido com dois pontos. Como é, podemos facilmente adicionar esses dois pontos e removê-los depois.

# 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

festa Pura:.)

Aqui está a solução mais simples que posso conceber:

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

O exemplo acima irá remover qualquer elemento em $ PATH que contém "usr". Você pode substituir "* usr *" com "/ home / user / bin" para remover apenas esse elemento.

update por sschuberth

Mesmo que eu acho espaços em um $PATH são um horrível idéia, aqui está uma solução que lida com isso:

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

Aqui está uma frase que, apesar da atual aceito e mais alta nominal respostas, não adiciona caracteres invisíveis a PATH e pode lidar com caminhos que contêm espaços:

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

Pessoalmente, eu também encontrar este fácil de ler / entender, e isso envolve apenas os comandos mais comuns em vez de usar awk.

Aqui está uma solução que:

  • é puro Bash,
  • não invoca outros processos (como 'sed' ou 'awk'),
  • não muda IFS,
  • não desembolsar um sub-shell,
  • alças caminhos com espaços, e
  • remove todas as ocorrências do argumento em PATH.

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

função __path_remove () {
D locais = ": $ {PATH}:";
[ "$ {D /: $ 1: /:}" = "$ D"!] && PATH = "$ {D /: $ 1: /:}";
PATH = "$ {PATH / #: /}";
export PATH = "$ {PATH /%: /}";
}

Dug-lo para fora do meu arquivo .bashrc. Quando você brincar com PATH, e ela se perde, awk / sed / grep fica indisponível: -)

A melhor opção festa pura eu encontrei até agora é a seguinte:

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
}

Este é baseado no não resposta totalmente correta para Adicione o diretório para $ PATH se ele não estiver lá mais em superusuário.

Acabei vindo a utilizar as funções na distribuição do bash, que foram lá, aparentemente, desde 1991. Estes ainda estão no pacote bash-docs no Fedora, e usados ??para ser usado em /etc/profile, mas não mais ...

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

Eu escrevi uma resposta a esta aqui (usando awk também). Mas eu não tenho certeza que é o que você está procurando? É, pelo menos, parece claro para mim o que ele faz, em vez de tentar caber em uma linha. Para um forro de um simples, porém, que apenas remove o material, eu recomendo

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

Substituir é

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

ou (mais curto, mas menos legível)

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

De qualquer forma, para a mesma pergunta, e um monte de respostas úteis, consulte aqui .

Bem, em bash, como ele suporta expressão regular, gostaria apenas de fazer:

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

O que é a maneira mais elegante para remover um caminho a partir da variável $ PATH em Bash?

O que é mais elegante do que awk?

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

Python! É uma solução mais legível e de fácil manutenção, e é fácil para inspecionar para ver que ele está realmente fazendo o que você quer.

Digamos que você queira remover o primeiro elemento de caminho?

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

(Em vez de tubulação de echo, os.getenv['PATH'] seria um pouco mais curto, e desde que o mesmo resultado que o anterior, mas estou preocupado que Python pode fazer algo com essa variável de ambiente, por isso é provavelmente melhor para canalizá-lo directamente a partir o ambiente que se preocupam.)

Da mesma forma para remover a partir do final:

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

Para fazer estas funções shell reutilizáveis ??que você pode, por exemplo, pau no seu arquivo .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))")"
}

Sim, colocar uma vírgula no final da PATH, por exemplo, faz a remoção de um caminho um pouco menos desajeitado e propenso a erros.

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 você está preocupado sobre como remover duplicatas em $ PATH, a maneira mais elegante, IMHO, seria não adicioná-los em primeiro lugar. Em 1 linha:

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

$ pasta pode ser ser substituído por qualquer coisa, e pode conter espaços ( "home / user / Meus Documentos /")

A solução pura festa elegante mais que eu encontrei até agora:

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

A maioria das outras soluções sugeridas contar apenas com strings e não levam em conta os segmentos de caminho contendo nomes especiais como ., .., ou ~. A função do bash abaixo cordas Directory resolve em seu argumento e em segmentos de caminho para encontrar partidas diretório lógico, bem como jogos de cordas.

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 define três funções de Bash em /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

Eu gosto das três funções mostradas na @ atualização do BenBlank à sua pergunta original. Para generalizar-los, eu uso uma forma 2-argumento, que me permite set PATH ou qualquer outra variável de ambiente que eu quero:

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

Exemplos de uso:

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

Note que eu também acrescentou algumas aspas para permitir o tratamento adequado dos caminhos que contêm espaços.

Uma vez que este tende a ser bastante problemático, como em Não há maneira elegante, eu recomendo evitar o problema, reorganizando a solução:. Construir o seu PATH-se em vez de tentativa de derrubá-lo

Eu poderia ser mais específico, se eu soubesse o contexto do problema real. Nesse ínterim, vou usar uma compilação de software como o contexto.

Um problema comum com o software constrói é que ele quebra em algumas máquinas, em última análise, devido à forma como alguém configurou sua shell default (PATH e outras variáveis ??de ambiente). A solução elegante é fazer com que seus scripts de construção imunológico especificando totalmente o ambiente shell. Código seus scripts de construção para definir as variáveis ??PATH e outro ambiente com base na montagem de peças que você controla, como a localização do compilador, bibliotecas, ferramentas, componentes, etc. Certifique cada item algo configurável que você pode definir individualmente, verificar e em seguida, usar adequadamente em seu script.

Por exemplo, eu tenho uma compilação Java WebLogic-alvo baseados em Maven que herdei de meu novo empregador. O script de construção é notório por ser frágil, e um outro empregado novo e eu passamos três semanas (não em tempo integral, apenas aqui e ali, mas ainda muitas horas) coloca-lo para trabalhar em nossas máquinas. Um passo essencial era que eu assumiu o controle da PATH para que eu sabia exatamente o que Java, que Maven, e que WebLogic estava sendo invocado. Eu criei as variáveis ??de ambiente para apontar para cada uma dessas ferramentas, então eu calculou o PATH baseados naqueles além de alguns outros. Técnicas similares domado as outras definições configuráveis, até que finalmente criou uma compilação reprodutível.

A propósito, não use o Maven, Java é bom, e só comprar WebLogic se você realmente precisa seu agrupamento (mas caso contrário não, e especialmente não suas características proprietárias).

Os melhores cumprimentos.

Tal como acontece com @ litb, eu contribuí uma resposta para a pergunta " Como faço para manipular $ elementos caminho no shell scripts ", por isso a minha resposta principal está lá.

A funcionalidade 'dividido' em outros derivados Bourne Shell bash e é mais perfeitamente alcançado com $IFS, o separador de inter-campo. Por exemplo, para definir os argumentos posicionais ($1, $2, ...) para os elementos da PATH, use:

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

Ele vai trabalhar OK, desde que não haja espaços em $ PATH. Fazendo o trabalho para elementos de caminho contendo espaços é um exercício não trivial - partiu para o leitor interessado. É provavelmente mais simples de lidar com ele usando uma linguagem de script como Perl.

Eu também tenho um script, clnpath, que eu uso extensivamente para definir o meu caminho. Eu documentei-o na resposta à pergunta " Como manter de duplicação variável PATH em csh ".

O que torna este problema irritante são os casos fencepost entre primeiro e último elementos. O problema pode ser elegantemente resolvido mudando IFS e usando uma matriz, mas eu não sei como a re-introduzir o cólon uma vez o caminho é convertido em forma de matriz.

Aqui está uma versão um pouco menos elegante que remove um diretório de $PATH usando apenas a manipulação de cadeia. Eu testei-o.

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

Aqui está um one-liner Perl:

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

A variável $a obtém o caminho a ser removido. O s (substituto) e print comandos operam implicitamente na variável $_.

Good stuff aqui. Eu uso este para evitar a adição de dupes em primeiro 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

Com alargada englobamento habilitado é possível fazer o seguinte:

# 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

Extensão englobamento one-liner (bem, mais ou menos):

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

Parece que não há necessidade de escapar barras em $ 1.

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

A adição de dois pontos para PATH também poderíamos fazer 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 

Em path_remove_all (por proxxy):

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

Enquanto este é um fio muito velha, eu pensei que esta solução poderia ser de 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

encontrado neste blog . Eu acho que como este mais:)

Eu levei uma abordagem um pouco diferente do que a maioria das pessoas aqui e focado especificamente sobre a manipulação de cadeia apenas, assim:

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

A descrição acima é um exemplo simplificado das funções finais eu uso. Também criei path_add_before e path_add_after permitindo que você inserir um caminho de antes / depois de um caminho especificado já no PATH.

O conjunto completo de funções estão disponíveis no path_helpers.sh na minha dotfiles . Eles totalmente apoiar a remoção / acrescentando / prepending / inserção no início / meio end / da cadeia de caminho.

A fuga ':' é causado pelo fato de que você está definindo o final de linha, não o separador. Eu uso unidades de recurso limitted e como empacotar tudo em um único roteiro, sem essas esquisitices:

path_remove () {
    PATH="$(echo -n $PATH | awk -v RS=: -v ORS= '$0 != "'$1'"{print s _ $0;s=":"}')"
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top