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

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

например, repo forall -c '....$variable'

В этом формате $ экранируется, и переменная не расширяется.

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

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

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

Пожалуйста, скажите мне, где я буду ошибаться.

    Внутри одинарных кавычек все сохраняется буквально, без исключения.

    Это означает, что вам нужно закрыть кавычки, вставить что-то, а затем снова ввести снова.

     'before'"$variable"'after' 'before'"'"'after' 'before'\''after' 

    Как вы можете проверить, каждая из вышеперечисленных строк представляет собой одно слово для оболочки. Сопоставление строк просто выполняется путем сопоставления. Котировки (одиночные или двойные кавычки, в зависимости от ситуации) используются для отключения интерпретации различных специальных символов, таких как пробелы, $ ,; … Для хорошего руководства по цитированию см. Ответ Марка Рида. Также уместно: какие символы нужно избегать в bash?

    Не объединяйте строки, интерпретируемые оболочкой

    Вы должны избегать создания команд оболочки путем объединения переменных. Это плохая идея, подобная конкатенации fragmentов SQL (SQL-инъекция!).

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

    Например, следующее очень опасно. НЕ ДЕЛАЙТЕ ЭТО

     script="echo \"Argument 1 is: $myvar\"" /bin/sh -c "$script" 

    Если содержимое $myvar , вот эксплойт:

     myvar='foo"; echo "you were hacked' 

    Вместо вышеупомянутого вызова используйте позиционные аргументы. Следующий вызов лучше – он не используется:

     script='echo "arg 1 is: $1"' /bin/sh -c "$script" -- "$myvar" 

    Обратите внимание на использование одиночных тиков в присваивании script , что означает, что это принято буквально, без изменения переменной или какой-либо другой интерпретации.

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

     repo forall -c 'literal stuff goes here; '"stuff with $parameters here"' more literal stuff' 

    Объяснение следует, если вам интересно.

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

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

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

    echo \"Thank\ you.\ \ That\'ll\ be\ \$4.96,\ please,\"\ said\ the\ cashier

    … это может стать утомительным. Таким образом, shell предлагает альтернативу: кавычки. Они бывают двух основных сортов.

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

    echo "\"Thank you. That'll be \$4.96, please,\" said the cashier"

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

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

    echo '"Thank you. That'\''ll be $4.96, please," said the cashier'

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

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

     echo $'"Thank you. That\'ll be $4.96, please," said the cashier' 

    Важно отметить, что единственная строка, полученная как аргумент команды echo , во всех этих примерах одинакова . После того, как shell закончила синтаксический анализ командной строки, для запуска этой команды нет способа сообщить, что было указано. Даже если захочет.

    EDIT: (В соответствии с комментариями, о которых идет речь 🙂

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

    Ниже было то, что сработало для меня –

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

    Это работает для вас?

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

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

     myvar=\'....$variable\' repo forall -c $myvar 
    Давайте будем гением компьютера.