Добавлять переменную в стиле PATH без создания начального двоеточия, если не установлено

10

Мне нужно добавить каталог в PKG_CONFIG_PATH. Обычно я бы использовал стандарт

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

но PKG_CONFIG_PATHне было ранее установлено в моей системе. Следовательно, переменная начинается с :символа, который говорит ей сначала искать в текущем каталоге. Я не хочу этого. Я остановился на следующем,

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

но это только кажется таким уродливым Есть ли способ лучше? Как правильно добавить двоеточие по условию, если и только если переменная уже установлена?

scottbb
источник
1
stackoverflow.com/questions/9631228/…
sancho.s ReinstateMonicaCellio

Ответы:

13

Вы находитесь на правильном пути с ${:+}оператором расширения, вам просто нужно немного его изменить:

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

Первые фигурные скобки расширяются до, $V и двоеточие iff Vуже установлено в противном случае в ничто - это именно то, что вам нужно (и, вероятно, также одна из причин существования оператора).

Таким образом, в вашем случае:

export "PKG_CONFIG_PATH=${PKG_CONFIG_PATH:+${PKG_CONFIG_PATH}:}$(pyenv prefix)/lib/pkgconfig"
peterph
источник
Я использовал эту форму, но я отказался от нее, потому что она была (немного) менее читабельной: ${V}${V:+:}Wпротив ${V:+${V}:}W. В любом случае, они оба чувствуют себя ужасно. Я надеялся на что-то ... более элегантное, я полагаю?
scottbb
@scottbb - это синтаксическая форма - так и делается. Если вы хотите установить значение переменной на основе условия, вы должны сделать тест. Вы можете выполнить встроенный тест, как написано здесь, или вы можете явно выполнить тестирование test- в любом случае вы проверяете значение и пишете переменную дважды, но таким образом вы делаете это в одном операторе выполнения - таким образом, это практично Но я никогда не встречал элегантный компьютер.
mikeserv
@scottbb Думая об этом, это действительно то же самое. Но я боюсь, что вы не получите его лучше, так как в основном вам нужно имя переменной в условии, а затем в расширении - я не думаю, что есть конструкция оболочки, которая сделала бы это только с одним вхождением имя.
Петер
@mikeserv - я, вероятно, должен был быть более точным, чем сказать, что я искал более «элегантное» решение. Я никогда не видел, чтобы это было сделано для добавления подстрок к переменным в стиле PATH, и мне казалось, что я упустил лучший способ. По моему опыту, когда я это чувствую, обычно есть лучший путь. Это то, что я должен был сказать. Но ваша точка зрения хорошо принята. Спасибо за ваш ответ. Также: в одном из ваших правок комментария @ peterph вы сделали комментарий, которому я должен был процитировать весь аргумент export. Это очень хороший момент, я тоже обдумал эту деталь.
scottbb
@scottbb - извините, если это прозвучало как абразив - я никогда не понимал концепцию элегантности в отношении вычислений. компьютер - это машина - три пути и / или ворота, сложенные миллиарды раз. он не может считаться выше единицы - во всех отношениях все, что он делает, является грубым . некоторые интуитивные понятия может быть легче перевести, чем другие, но, если это так, то это только потому, что концепция лежит поверх какой-то другой грубой абстракции. В основе вычислений всегда лежит элегантность.
mikeserv
1

В последнее время я установил GNU- хранилище на своих машинах, чтобы хранить под ним пользовательские вещи, такие как библиотеки, ~/.localи столкнулся с проблемами при определении LD_LIBRARY_PATH, CPATHи LIBRARY_PATH, непреднамеренно вставив туда двоеточие и таким образом испортив вещи.

Тогда я нашел ваш вопрос, и ответ был не совсем элегантным ;-), и я написал небольшую функцию, чтобы справиться с этим, пожалуйста, найдите его здесь: https://gist.github.com/rico-chet/0229e4c080d9f51a02535dd25a656a8a

## Copyright (C) 2018 Alex Thiessen <alex.thiessen.de+github@gmail.com>
## Copyright (C) 2018 https://unix.stackexchange.com/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 "${*}")"
}

// отредактировано в соответствии с предложением @Kusalananda

Superlexx
источник
Также:( IFS=:; set -- 1 2 3 4 5 6; echo "$*" )
Кусалананда
Т.е.:join () { var=$1; shift; export "$var"="$( IFS=:; echo "$*" )"; }
Кусалананда
... За исключением того, что "join" является неудачным именем, так как оно также является названием стандартной утилиты.
Кусалананда
Хороший, за исключением того факта, что вы перезаписали бы переменную вместо добавления к ней. Просто добавление ${!variable:+${!variable}:}в нужном месте сработало для меня, все тесты пройдены. Поиск подходящего имени - это простое упражнение для читателя :)
Superlexx