Как напечатать «$» в здесь-документе

42

Как я могу отобразить "$" в документах here в bash?

Например, я хочу иметь файл с содержимым на удаленном сервере, как $ABC=home_dir.

$ ssh hostname sudo -s <<EOF
echo "$ABC=home_dir" > file
EOF

Но это будет рассматриваться как переменная. Как я могу напечатать литерал $?

user21485
источник
2
Вы можете использовать одинарные кавычки
Рахул Патил
2
Это много косвенных событий. Вы уверены, что не можете создать файл на локальном хосте, а затем scpэто?
10

Ответы:

65

Если вы хотите написать здесь документ и не хотите, чтобы ЛЮБОЙ документ был расширен или какие-либо специальные символы интерпретировались, вы можете заключить в ярлык одинарные кавычки, например:

$ cat >file <<'EOF'
echo "$ABC=home_dir"
EOF

Однако ваша ситуация, описанная в вашем примере, намного сложнее, потому что вы действительно отправляете этот контент через ssh в удаленную систему, чтобы запустить sudo, которая также вызывает оболочку (и поэтому оболочка будет расширять содержимое также). Вам понадобятся дополнительные уровни цитирования, чтобы получить это право, но даже при этом он все равно не будет работать, потому что для sudo требуется терминал (чтобы он мог запрашивать пароль), и вы перенаправлены из stdin. Даже использование ssh -tздесь не поможет.

Также я согласен с Йоханом. Не ясно, действительно ли это то, что вы хотите; обратите внимание, что присвоение значения для ссылки на переменную оболочки недопустимо, поэтому если этот файл, который вы пытаетесь создать, должен быть сценарием оболочки, он не будет работать так, как вы его описали. Может быть, если вы сделаете резервную копию и опишите, что вы действительно хотите сделать, мы можем помочь больше.

Сумасшедший ученый
источник
Это лучший ответ, потому что он может обслуживать очень длинные ЗДЕСЬ документы. Это (в основном) идиотизм.
Фелипе Альварес
22

Избежать $

$ ssh hostname sudo -s <<EOF
echo "\$ABC=home_dir" > file
EOF

Я не знаю, каков ваш вариант использования, но обычно вы хотите home_dir=$ABCвместо $ABC=home_dir.

lesmana
источник
2
Это решение будет работать, но действительно ли этого хочет ОП? Похоже, он генерирует сценарий оболочки, который при выполнении будет хранить в «файле» строку, которая будет разыменовывать ABC для левой части присвоения и, вероятно, в конечном итоге будет сохранена =home_dirв файл? Конечно, я не знаю, каков вариант использования ...
Йохан
2
Это приведет $к отправке литерала в удаленную оболочку, но затем эта оболочка развернется, $ABCпрежде чем отобразить строку file. Чтобы записать литерал $в файл, вам понадобится еще одна (экранированная) обратная косая черта:, echo "\\\$ABC=home_dir"чтобы удаленная оболочка получила echo "\$ABC=home_dir".
chepner
9

Самый дешевый способ избежать

$ ssh hostname sudo -s << \EOF
echo "$ABC=home_dir" > file
EOF
Бернхард
источник
4

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

echo 'echo $ABC=home_dir' | ssh hostname sudo -s "cat > file"

Одинарные кавычки защищают $на локальном конце, и строка никогда не видна оболочкой на другом, потому что она читается напрямую cat(через sudo), а не является аргументом для другой команды оболочки.

С вашим кодом вам понадобится дополнительный уровень экранирования для защиты $:

$ ssh hostname sudo -s <<EOF
echo "\\\$ABC=home_dir" > file
EOF

Вам необходимо отправить литерал \$на удаленный хост, чтобы удаленная оболочка записала литерал $в файл. Вы также можете упростить это, указав маркер here-doc:

$ ssh hostname sudo -s <<\EOF
echo "\$ABC=home_dir" > file
EOF
chepner
источник