Вызов 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 

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

  • Удаление всех файлов, начинающихся со скобок
  • sed для сопоставления между совпадающими фигурными фигурными скобками
  • ESC-q не работает в tmux с zsh
  • Исключение переменных gawk для команд оболочки
  • Терминальные escape-последовательности: почему терминалы не сообщают, какие функции они поддерживают, вместо того, чтобы полагаться на terminfo?
  • sh -c: Неудачная строка с котировкой строки
  • как правильно планировать задачу, которая планирует задачу с помощью «at» (atd)? или как правильно указывать / бежать в bash
  • Почему я должен дважды уйти от «точки»?
  • Визуализация кода escape-кода ansi в файлах журналов правильно в Emacs
  • Найдите комбинацию клавиш терминала OS X / escape-последовательность для Ctrl-
  • Как правильно избежать этой длинной команды su + sed?
  • Interesting Posts

    В чем разница между ** pts ** и ** tty ** и **: 0 **?

    Как показать значок приложения в контекстном меню «открыть с» для пользовательского mimetype в Linux Mint Cinnamon?

    Процессы теряют привязку к оболочке при запуске через bash -x

    Поиск всех жестких ссылок файла без прохождения файловой системы

    Как добавить задания cron на мой маршрутизатор? У меня есть доступ к SSH

    Является ли Линус Торвальдс хакером?

    Командная строка эквивалентна «Безопасно удалить диск»?

    Внедрить включение другого файла в поток (чтение из stdin)

    Фильтрация и извлечение PID в виде списка разделенных пробелами из ps с помощью sed

    30 секунд в процессе загрузки

    как я могу исключить конкретную папку в пункте назначения при использовании rsync?

    В Ubuntu – / var / log / messages отметки времени на 4 минуты вперед

    Сдвиг GNOME 3 верхний левый горячий угол на левый край экрана

    Как rsync файлы между двумя пультами с явным портом и разными именами пользователей?

    Использование sed для удаления целой строки, если оно содержит только определенный номер

    Linux и Unix - лучшая ОС в мире.