Вызов bash из sh (тире) с командами, считанными из args, и «Unterminated quoteed string» / «неожиданный EOF»

Просто подумал, что я документирую это: я пытаюсь сделать что-то очень простое – установите переменную env в bash и распечатайте ее:

 $ bash -c "a=1; echo a$a;" a $ bash -c "a=1; echo a\$a;" a1 

Теперь я хотел бы получить эту же вещь, но был вызван как аргумент sh (в моей системе ls -la $(which sh) дает /bin/sh -> dash ):

 $ sh -c "bash -c "a=1; echo a\$a;"" a$a # obviously I have to escape inner quotes: $ sh -c "bash -c \"a=1; echo a\$a;\"" a # escape the dollar once more? $ sh -c "bash -c \"a=1; echo a\\$a\" " sh: Syntax error: Unterminated quoted string # nope... inner single quotes, then? $ sh -c "bash -c 'a=1; echo a$a;'" a # nope... escape the single quotes? $ sh -c "bash -c \'a=1; echo a$a;\'" bash: -c: line 0: unexpected EOF while looking for matching `'' bash: -c: line 1: syntax error: unexpected end of file a sh: ': not found # nope... escape the dollar too? $ sh -c "bash -c \'a=1; echo a\$a;\'" bash: -c: line 0: unexpected EOF while looking for matching `'' bash: -c: line 1: syntax error: unexpected end of file a sh: ': not found размере $ sh -c "bash -c "a=1; echo a\$a;"" a$a # obviously I have to escape inner quotes: $ sh -c "bash -c \"a=1; echo a\$a;\"" a # escape the dollar once more? $ sh -c "bash -c \"a=1; echo a\\$a\" " sh: Syntax error: Unterminated quoted string # nope... inner single quotes, then? $ sh -c "bash -c 'a=1; echo a$a;'" a # nope... escape the single quotes? $ sh -c "bash -c \'a=1; echo a$a;\'" bash: -c: line 0: unexpected EOF while looking for matching `'' bash: -c: line 1: syntax error: unexpected end of file a sh: ': not found # nope... escape the dollar too? $ sh -c "bash -c \'a=1; echo a\$a;\'" bash: -c: line 0: unexpected EOF while looking for matching `'' bash: -c: line 1: syntax error: unexpected end of file a sh: ': not found 

Итак, мой вопрос будет: какой правильный синтаксис для экранирования, так что sh -c [bash -c ...] дает тот же результат, что и bash -c ... ?

2 Solutions collect form web for “Вызов bash из sh (тире) с командами, считанными из args, и «Unterminated quoteed string» / «неожиданный EOF»”

Внутри одинарных кавычек символ не имеет особого значения. Внутри двойных кавычек "\$` имеют особое значение. Разработайте его снаружи: сначала выясните, какая строка построена внешней оболочкой, а затем внутренняя оболочка сделает из нее.

Например, предположим, что переменная a не определена во внешней оболочке, с

 sh -c "bash -c \"a=1; echo a\$a;\"" 

внешняя оболочка видит строку с двойными кавычками, которая расширяется до bash -c "a=1; echo a$a;" , и это строка, которая передается промежуточному sh . sh анализирует это как вызов bash с двумя аргументами -c и a=1; echo a; a=1; echo a; , последний в результате расширения строки с двойными кавычками "a=1; echo a$a;" где переменная a не определена.

Если вы сделаете этот анализ, вы увидите, что один из способов получить то, что вы хотите, будет иметь "a=1; echo a\$a;" на данном этапе. Чтобы получить эту дополнительную обратную косую черту, вам нужно поместить две обратной косой черты в оригинал, так как уже существует один этап расширения оболочки внутри двойных кавычек. Два плюс один – три.

 sh -c "bash -c \"a=1; echo a\\\$a;\"" 

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

 sh -c 'bash -c "a=1; echo a\$a;"' 

Поскольку вы не хотите расширять что-либо, когда вы вызываете bash из sh , вы также можете использовать одинарные кавычки. Вы не можете поместить одинарные кавычки внутри одной кавычки, но есть способ имитировать это: put '\'' . Формально это завершает однокасканный литерал, добавляет буквенную одинарную кавычку и запускает новый однокасканный литерал, но вы можете думать о четырехсимвольной последовательности '\'' как о способе поставить одну цитату внутри одного -котированная строка.

 sh -c 'bash -c '\''a=1; echo a$a;'\''' 

Вы можете опустить это '' в конце концов, это менее систематично, но проще на глазах.

 sh -c 'bash -c '\''a=1; echo a$a;'\' 

Одиночные кавычки не являются специальными внутри двойных кавычек, поэтому, когда вы пишете "bash -c 'a=1; echo a\$a;'" вам нужна обратная косая черта перед долларом, чтобы предотвратить расширение $a во внешней оболочке.

Ну, я нашел пару, которая работает (NB, это Ubuntu 11.04):

 $ sh -c "bash -c 'a=1; echo a\$a \'" a1 $ sh -c "bash -c 'a=1; echo a\$a;'" a1 

… и кажется, до тех пор, пока первая одинарная кавычка не будет сохранена, а доллар будет экранирован – он работает, несмотря на то, что последняя одиночная цитата сбежала или нет! Который озадачивает меня совсем немного …

  • Как создать команду bash, которая создает вывод, который точно имитирует исходный текстовый файл, который можно вставить в оболочку bash, где включен histexpand?
  • Гармонический текст в меню tmux
  • Обратный код управления ищет терминалы
  • Как использовать сеанс ssh без форматирования цвета
  • Как сбежать в YAML правильно?
  • Другой вопрос об исключении строки Bash (с использованием эха)
  • Правильное использование escape-символов в файле рабочего стола
  • Попытка распечатать клавиши со стрелками вниз
  • Есть ли причина, по которой я получаю ^ [[A, когда я нажимаю стрелку на экране входа в консоль?
  • Bash: экранированные кавычки в подоболочке
  • Белл и escape-символ в строке подсказки
  • Linux и Unix - лучшая ОС в мире.