Ou, de forma mais geral, como removo um item de uma lista separada por dois pontos em uma variável de ambiente Bash?
Eu pensei ter visto uma maneira simples de fazer isso anos atrás, usando as formas mais avançadas de expansão de variável Bash, mas se foi, perdi o controle. Uma busca rápida no Google encontrou surpreendentemente poucos resultados relevantes e nenhum que eu chamaria de "simples" ou "elegante". Por exemplo, dois métodos usando 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)
Não existe nada simples? Existe algo análogo a uma função split () no Bash?
Atualizar:
Parece que preciso me desculpar por minha pergunta intencionalmente vaga; Eu estava menos interessado em resolver um caso de uso específico do que em provocar uma boa discussão. Felizmente, consegui!
Existem algumas técnicas muito inteligentes aqui. No final, adicionei as três funções a seguir à minha caixa de ferramentas. A mágica acontece em path_remove, que é amplamente baseado no uso inteligente de Martin York da awk
variável 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/:$//'`; }
O único problema real é o uso de sed
para remover os dois pontos à direita. Considerando o quão simples é o resto da solução de Martin, estou bastante disposto a viver com isso!
Questão relacionada: Como posso manipular elementos $ PATH em scripts de shell?
WORK=`echo -n ${1} | awk -v RS=: -v ORS=: '$0 != "'${3}'"' | sed 's/:$//'`; eval "export ${2}=${WORK}"
mas você deve chamá-la comofunc $VAR VAR pattern
(com base em @ martin-york e @andrew-aylett)