Anexar à variável do tipo PATH sem criar dois pontos à esquerda se não estiver definido

10

Eu preciso anexar um diretório para PKG_CONFIG_PATH. Normalmente, eu usaria o padrão

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}:$(pyenv prefix)/lib/pkgconfig

mas PKG_CONFIG_PATHnão foi definido anteriormente no meu sistema. Portanto, a variável começa com um :caractere, que diz para procurar primeiro no diretório atual. Eu não quero isso. Eu decidi o seguinte,

export PKG_CONFIG_PATH=${PKG_CONFIG_PATH}${PKG_CONFIG_PATH:+:}$(pyenv prefix)/lib/pkgconfig

mas isso parece tão feio. Existe uma maneira melhor? Qual é a maneira apropriada de anexar condicionalmente os dois pontos se e somente se a variável já tiver sido definida?

scottbb
fonte
1
stackoverflow.com/questions/9631228/…
sancho.s ReinstateMonicaCellio

Respostas:

13

Você está no caminho certo com o ${:+}operador de expansão, basta modificá-lo um pouco:

V=${V:+${V}:}new_V

As primeiras chaves se expandem para $V e o cólon iff Vjá está definido como nada - o que é exatamente o que você precisa (e provavelmente também uma das razões para a existência do operador).

Assim, no seu caso:

export "PKG_CONFIG_PATH=${PKG_CONFIG_PATH:+${PKG_CONFIG_PATH}:}$(pyenv prefix)/lib/pkgconfig"
peterph
fonte
Eu estava usando essa forma, mas decidi contra ela porque sentia (ligeiramente) menos legível: ${V}${V:+:}Wvs. ${V:+${V}:}W. De qualquer forma, ambos se sentem muito feios. Eu estava esperando algo ... mais elegante, eu acho?
scottbb
@ scottbb - esta é a forma da sintaxe - é assim que é feita. Se você deseja definir o valor de uma variável com base em uma condição, é necessário fazer um teste. Você pode fazer um teste em linha, como está escrito aqui, ou pode testar explicitamente com test- de qualquer maneira, você está testando o valor e escrevendo o varname duas vezes, mas dessa maneira você faz isso em uma única instrução de execução -, dessa maneira é prático , mas nunca conheci um computador elegante .
mikeserv
@scottbb Pensando nisso, realmente é o mesmo. Mas receio que você não melhore, pois você basicamente precisa do nome da variável na condição e depois na expansão - não acho que exista uma construção de shell que faria isso com apenas uma ocorrência do nome.
Peterph
@mikeserv - Eu provavelmente deveria ter sido mais preciso do que dizer que estava procurando uma solução mais "elegante". Eu realmente nunca vi isso feito para anexar substrings a variáveis ​​no estilo PATH, e parecia que estava perdendo uma maneira melhor. Na minha experiência, quando sinto esse sentimento, geralmente há uma maneira melhor. Isso é o que eu deveria ter dito. Mas seu ponto de vista é bem aceito. Obrigado pela sua resposta. Além disso: em uma das suas edições do comentário de @ peterph, você fez o comentário ao qual eu deveria ter citado todo o argumento export. Esse é um ponto muito bom, também ofendi esses detalhes.
scottbb
@ scottbb - desculpe se isso saiu como abrasivo - nunca entendi o conceito de elegância em relação à computação. um computador é uma máquina - um sistema de três vias e / ou portão composto bilhões de vezes. não pode contar mais do que um - em todos os aspectos, tudo o que faz é forçado por força bruta . alguns conceitos intuitivos podem ser mais fáceis de traduzir do que outros, mas, se for o caso, é apenas porque o conceito fica no topo de alguma outra abstração forçada bruta. a computação, em sua essência, é sempre tudo menos elegante.
mikeserv
1

Ultimamente, eu instalei o GNU stow em minhas máquinas para armazenar coisas de todo o usuário, como bibliotecas, ~/.locale tive problemas ao definir LD_LIBRARY_PATH, CPATHe LIBRARY_PATH, inadvertidamente, colocando dois pontos lá e quebrando coisas.

Então encontrei sua pergunta e a resposta não era exatamente elegante ;-) e escrevi uma pequena função para lidar com isso, localize-a aqui: https://gist.github.com/rico-chet/0229e4c080d9f51a02535dd25a656a8a

## Copyright (C) 2018 Alex Thiessen <[email protected]>
## Copyright (C) 2018 /unix//users/116858/kusalananda
## SPDX-License-Identifier: GPL-2.0-or-later
## <https://spdx.org/licenses/GPL-2.0-or-later.html>

function join() {
    if [ ${#} -eq 0 ]
    then
        echo "\`join\` appends elements separated by colons to a \`bash\` variable " >&2
        echo "usage: join <variable> <element> [element ...]" >&2
        return 1
    fi
    variable="${1}"

    shift
    export ${variable}="${!variable:+${!variable}:}$(IFS=:; echo "${*}")"
}

// editado como sugerido por @Kusalananda

Superlexx
fonte
Também:( IFS=:; set -- 1 2 3 4 5 6; echo "$*" )
Kusalananda
join () { var=$1; shift; export "$var"="$( IFS=:; echo "$*" )"; }
Ou
... Exceto que "ingressar" é um nome infeliz, pois também é o nome de um utilitário padrão.
Kusalananda
Bom, exceto pelo fato de você sobrescrever a variável em vez de anexá-la. Apenas adicionar ${!variable:+${!variable}:}no lugar certo funcionou para mim, todos os testes passaram. Encontrar um nome apropriado é uma exersize para o leitor :)
Superlexx