Добавлять переменную в стиле 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

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


Ответы:


13

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

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

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

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

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

Я использовал эту форму, но я отказался от нее, потому что она была (немного) менее читабельной: ${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


Также:( IFS=:; set -- 1 2 3 4 5 6; echo "$*" )
— Кусалананда

Т.е.:join () { var=$1; shift; export "$var"="$( IFS=:; echo "$*" )"; }
— Кусалананда

... За исключением того, что "join" является неудачным именем, так как оно также является названием стандартной утилиты.
— Кусалананда

Хороший, за исключением того факта, что вы перезаписали бы переменную вместо добавления к ней. Просто добавление ${!variable:+${!variable}:}в нужном месте сработало для меня, все тесты пройдены. Поиск подходящего имени - это простое упражнение для читателя :)
— Superlexx
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.