6

Расширение переменных внутри одинарных кавычек в команде Bash

9

Проблема с использованием переменной в однострочном Bash-скрипте

Я хочу запустить команду из bash-скрипта, в которой используются одинарные кавычки и некоторые другие команды внутри этих кавычек, а также переменная.

Например, команда выглядит так: repo forall -c '....$variable'.

В таком формате символ $ экранируется, и переменная не раз expands.

Я пробовал следующие варианты, но они не сработали:

repo forall -c '...."$variable" '

repo forall -c " '....$variable' "

" repo forall -c '....$variable' "

repo forall -c "'" ....$variable "'"

Когда я подставляю значение переменной непосредственно в команду, она выполняется без проблем.

Подскажите, где я ошибаюсь?

5 ответ(ов)

1

Команда repo не обращает внимания на то, какие кавычки вы используете. Если вам нужно расширение параметров, используйте двойные кавычки. Если это означает, что вам придется много экранировать, используйте одинарные кавычки для большей части, а затем вырывайтесь из них и переходите к двойным там, где необходимо сделать расширение.

Пример:

repo forall -c 'литерал здесь; '"строка с $параметрами здесь"' еще один литерал'

Если вам интересно, то вот пояснение.

Когда вы запускаете команду из оболочки, то эта команда получает аргументы в виде массива строк, оканчивающихся на ноль. Эти строки могут содержать абсолютно любые символы, за исключением нуля.

Однако, при построении этого массива строк из командной строки оболочка интерпретирует некоторые символы особым образом; это сделано для упрощения (и даже возможности) ввода команд. Например, пробелы обычно указывают на границы между строками в массиве; по этой причине строки в оболочке часто называют "словами". Тем не менее, слово в оболочке может содержать пробелы; вам просто нужно каким-то образом сообщить оболочке, что вы именно это и хотите.

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

Двойные кавычки часто называют "группировочными кавычками". Они предотвращают расширение подстановок и псевдонимов, но в основном они нужны для включения пробелов в слово. Другие подстановки, такие как расширение параметров и команд (например, за счет символа $), все равно происходят. Чтобы получить буквальный знак доллара или кавычку (или обратную косую черту) внутри строки в двойных кавычках, нужно экранировать его:

reply="\"Это будет \$4.96, пожалуйста,\" - сказал кассир"

Одиночные кавычки более строги. Все между одиночными кавычками воспринимается совершенно буквально, включая обратные косые черты. Невозможно получить буквальную одиночную кавычку внутри одиночных кавычек.

К счастью, кавычки в оболочке не являются разделителями слов; сами по себе они не заканчивают слово. Поэтому вы можете входить и выходить из кавычек, включая переход между разными типами кавычек, в рамках одного слова для достижения желаемого результата:

reply='"Это будет '\''$4.96, пожалуйста," - сказал кассир'

Это удобнее – гораздо меньше обратных косых черт, хотя последовательность закрывающей одиночной кавычки, экранированной одиночной кавычки и открывающей одиночной кавычки требует времени на привыкание.

Современные оболочки добавили еще один стиль кавычек, не указанный в стандарте POSIX, в котором ведущая одиночная кавычка предшествует знаком доллара. Строки, заключенные в такие кавычки, следуют аналогичным правилам, как строковые литералы в стандартной версии языка программирования C, и поэтому иногда называются "ANSI-строками", а пары $'...' - "ANSI-кавычками". В таких строках вышеупомянутое правило об экранировании обратной косой чертой больше не применимо. Напротив, они снова становятся специальными - вы можете включать буквальную одиночную кавычку или обратную косую черту, предварительно добавив перед ними обратную косую черту, а оболочка также расширяет ANSI C escape-последовательности (например, \n для новой строки, \t для табуляции и \xHH для символа с шестнадцатеричным кодом HH). В остальном они ведут себя как строки в одиночных кавычках: подстановка параметров или команд не происходит:

reply=$'"Это будет '\''$4.96, пожалуйста," - сказал кассир'

Важно отметить, что одна строка, которая сохраняется в переменной reply, абсолютно идентична во всех этих примерах. Аналогичным образом, после того как оболочка завершит анализ командной строки, команда, которая выполняется, не сможет точно определить, как каждая строка аргумента была фактически введена — или даже если она была введена, а не была создана программным путем.

0

Вот что сработало для меня:

QUOTE="'"
hive -e "alter table TBL_NAME set location $QUOTE$TBL_HDFS_DIR_PATH$QUOTE"

Убедитесь, что вы заменили TBL_NAME на имя вашей таблицы, а TBL_HDFS_DIR_PATH на нужный путь в HDFS.

0

Вместо использования

repo forall -c '....$variable'

можно применить printf, чтобы заменить токен переменной на развернутую переменную.

Например:

template='.... %s'

repo forall -c $(printf "${template}" "${variable}")

Таким образом, вы получите более чистый и наглядный код.

0

ИЗМЕНЕНИЕ: (Согласно комментариям к вопросу:)

С тех пор я немного разобрался в этом. Мне повезло, что у меня был репозиторий под рукой. Тем не менее, мне все еще не ясно, нужно ли обязательно заключать команды в одинарные кавычки. Я изучил синтаксис репозитория, и, как мне кажется, это не обязательно. Вы можете использовать двойные кавычки вокруг вашей команды и при этом использовать любые одинарные и двойные кавычки внутри, при условии, что экранируете двойные кавычки.

0

Переменные могут содержать одинарные кавычки.

В вашем примере, вы определяете переменную myvar, которая содержит строку с одинарной кавычкой, экранированной с помощью обратного слэша:

myvar=\'....$variable\'

Затем вы используете эту переменную в команде repo forall:

repo forall -c $myvar

Это означает, что содержимое переменной myvar будет подставлено в команду repo forall -c, и, поскольку вы экранировали одинарные кавычки, это позволит корректно обрабатывать строку, включая переменную $variable. Убедитесь, что переменная $variable определена и содержит необходимые данные, поскольку она будет расширена при выполнении команды.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь