Почему тильда в пути не раскрывается в сценарии оболочки?

Я попытался заставить средство запуска Android Studio (studio.sh) использовать мою установленную вручную Java (а не общесистемную Java по умолчанию). Поскольку я уже объявил PATH и JAVA_HOME в своем файле .bashrc, я просто использовал этот файл в сценарии оболочки:

. /дом/foobar/.bashrc

но по какой-то причине $JAVA_HOME/bin/java по-прежнему не распознавался сценарием как исполняемый файл.

Я добавил логирование и обнаружил, что JAVA_HOME был расширен как ~/install/java..., т.е. оператор тильды не был расширен в домашний каталог.

Я немного поискал, но не смог найти причину, по которой он не был расширен. Является ли тильда особенностью Bash (скрипт использует #!/bin/sh, а Linux Mint использует тире, а не bash)? Тильда не работает в некоторых случаях?

Я заменил ~ на $HOME в своем объявлении .bashrc, и тогда это сработало, поэтому HOME известен во время выполнения.


person Community    schedule 28.08.2015    source источник


Ответы (1)


В руководстве по bash обратите внимание, что раскрытие фигурной скобки во время подстановки параметров, но не рекурсивно:

Порядок раскрытия следующий: раскрытие фигурной скобки; расширение с помощью тильды, расширение параметров и переменных, арифметическое расширение и подстановка команд (выполняется слева направо); разделение слов; и расширение имени файла.

Это означает, что любая тильда (или ссылки на параметры или подстановка команд), хранящиеся в нераскрытом виде в переменной bash, не разрешаются автоматически. Ваша переменная JAVA_HOME содержит буквальную тильду, поэтому bash не будет расширять ее автоматически.

Вероятно, ваше исправление сработало, потому что расширение тильды не применяется в кавычках:

$ echo "~"
~
$ echo ~
/home/jeffbowman

... но расширение параметра, например $HOME, заключено в кавычки. Замена его на $HOME расширяет ваш домашний каталог во время назначения JAVA_HOME.

FOO=~/bar        # stores /home/jeffbowman/bar
FOO="~/bar"      # stores ~/bar
FOO=$HOME/bar    # stores /home/jeffbowman/bar
FOO="$HOME/bar"  # stores /home/jeffbowman/bar

Хотя лучший вариант — убедиться, что ваше задание правильное, если вы хотите расширить его вручную, у этих вопросов SO есть несколько хороших вариантов:

person Jeff Bowman    schedule 28.08.2015
comment
Этот ответ может быть лучшим, чтобы указать на него, но я действительно не смотрел на тот, на который вы ссылались, слишком внимательно . - person Etan Reisner; 28.08.2015
comment
@EtanReisner Спасибо. Есть несколько давних расширенных моих сохраненных вопросов с тильдой, которые могут потребовать дедупликации. Этот подходит; Я отредактирую его. (Я бы предпочел ссылку на вопрос, чем на ответ, потому что широта ответов полезна для понимания преимуществ и недостатков каждого из них.) - person Jeff Bowman; 28.08.2015
comment
Да, у меня некоторое время было открыто несколько таких вкладок, и я ждал, пока я решу, как их правильно дедублировать. Я почти опубликовал мета-вопрос о том, можно ли заставить модератора перенести некоторые из лучших ответов на новый канонически заданный вопрос или что-то в этом роде. - person Etan Reisner; 28.08.2015