So drucken Sie "$" in here-document

42

Wie kann ich "$" in einem Here-Doc in Bash ausgeben?

Zum Beispiel möchte ich eine Datei mit dem Inhalt auf einem entfernten Server haben $ABC=home_dir.

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

Aber es würde als Variable behandelt. Wie kann ich ein Literal drucken $?

user21485
quelle
2
Sie können einfache Anführungszeichen verwenden
Rahul Patil
2
Das ist eine Menge Indirektion. Sind Sie sicher, dass Sie die Datei nicht auf dem lokalen Host erstellen können und dann scp?
l0b0

Antworten:

65

Wenn Sie ein Here-Doc schreiben möchten und keines der Docs erweitert oder Sonderzeichen interpretiert werden sollen, können Sie das Label in einfache Anführungszeichen setzen:

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

Die in Ihrem Beispiel beschriebene Situation ist jedoch viel komplexer, da Sie diesen Inhalt wirklich über ssh an ein fernes System senden, das von sudo ausgeführt wird, das auch eine Shell aufruft (und die Shell den Inhalt erweitert) auch). Sie werden mehr Zitierstufen benötigen, um dies richtig zu machen, aber auch damit funktioniert es nicht, da sudo ein Terminal benötigt (so dass es nach einem Passwort fragen kann) und Sie von stdin umgeleitet haben. Auch die Verwendung ssh -twird hier nicht helfen.

Auch ich stimme Johan zu. Es ist nicht klar, dass dies wirklich das ist, was Sie wollen. Beachten Sie, dass es nicht zulässig ist, einer Shell-Variablenreferenz einen Wert zuzuweisen. Wenn es sich also bei der Datei, die Sie erstellen möchten, um ein Shell-Skript handelt, funktioniert es nicht so, wie Sie es beschrieben haben. Vielleicht können wir Ihnen weiterhelfen, wenn Sie ein wenig zurücktreten und beschreiben, was Sie wirklich tun möchten.

Verrückter Wissenschaftler
quelle
Dies ist die beste Antwort, da sie für sehr lange HIER-Dokumente geeignet ist. Es ist (meistens) idiotensicher.
Felipe Alvarez
22

Entfliehen Sie dem $

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

Ich weiß nicht, was Ihr Anwendungsfall ist, aber in der Regel möchten Sie home_dir=$ABCstatt $ABC=home_dir.

Lesmana
quelle
2
Diese Lösung wird funktionieren, aber ist das wirklich das, was das OP will? Es scheint ein Shell-Skript zu generieren, das bei Ausführung in "file" eine Zeichenfolge speichert =home_dir, die ABC für die linke Seite der Zuweisung dereferenziert und wahrscheinlich in der Datei gespeichert wird. Natürlich weiß ich nicht, was der Anwendungsfall ist ...
Johan
2
Dies bewirkt , dass eine wörtliche $an die entfernte Shell gesendet werden, aber dann , dass Shell zu erweitern , $ABCbevor Echo der Zeichenfolge file. Um das Literal $in die Datei zu schreiben , benötigen Sie einen weiteren (mit Escape-Zeichen versehenen) Backslash:, echo "\\\$ABC=home_dir"damit die Remote-Shell empfängt echo "\$ABC=home_dir".
Chepner
9

Der billigste Fluchtweg wäre

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

Sie sparen sich eine Quote, indem Sie die Zeichenfolge an einen catProzess auf der Remote-Seite senden :

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

Die einfachen Anführungszeichen schützen das $lokale Ende, und der String wird von der Shell auf der anderen Seite nie gesehen, da er direkt von cat(via sudo) gelesen wird , anstatt ein Argument für einen anderen Shell-Befehl zu sein.

Mit Ihrem Code benötigen Sie eine zusätzliche Escape-Ebene, um Folgendes zu schützen $:

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

Sie müssen ein Literal \$an den Remote-Host senden , damit die Remote-Shell ein Literal $in die Datei schreibt . Sie können dies auch vereinfachen, indem Sie den Here-Doc-Marker verwenden:

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