Wie entkomme ich Anführungszeichen in Shell?

65

Ich habe Probleme mit der Flucht vor Charakteren in der Bash. Ich möchte einfache und doppelte Anführungszeichen vermeiden, während ein Befehl unter einem anderen Benutzer ausgeführt wird. Nehmen wir zum Zweck dieser Frage an, ich möchte Folgendes auf dem Bildschirm wiedergeben:

'single quote phrase' "double quote phrase"

Wie kann ich alle Sonderzeichen umgehen, wenn ich auch zu einem anderen Benutzer wechseln muss:

sudo su USER -c "echo \"'single quote phrase' \"double quote phrase\"\""

Dies führt natürlich nicht zum richtigen Ergebnis.

m33lky
quelle
+1 für "Natürlich führt dies nicht zu den richtigen Ergebnissen". bashist auf dem besten Weg, mich wütend zu machen.
Rolf

Antworten:

88

Sie können die folgende String-Literal-Syntax verwenden:

> echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

Von man bash

Wörter der Form $ 'string' werden speziell behandelt. Das Wort wird zu einer Zeichenfolge erweitert, wobei mit einem Backslash versehene Zeichen gemäß dem ANSI C-Standard ersetzt werden. Escape-Sequenzen für umgekehrte Schrägstriche werden, falls vorhanden, wie folgt dekodiert:

          \a     alert (bell)
          \b     backspace
          \e
          \E     an escape character
          \f     form feed
          \n     new line
          \r     carriage return
          \t     horizontal tab
          \v     vertical tab
          \\     backslash
          \'     single quote
          \"     double quote
          \nnn   the eight-bit character whose value is the octal value nnn (one to three digits)
          \xHH   the eight-bit character whose value is the hexadecimal value HH (one or two hex digits)
          \cx    a control-x character
SiegeX
quelle
5
Overkill. In den meisten Fällen müssen Sie keine String-Literal-Syntax verwenden.
fpmurphy
Weitere Details hier stackoverflow.com/a/16605140/149221
mj41
12

Befolgen Sie in einer POSIX-Shell die folgenden grundlegenden Vorschriften, vorausgesetzt, in Ihrer Zeichenfolge gibt es keine Variablen-, Befehls- oder Verlaufserweiterung und keine Zeilenumbruchzeile:

  1. Führen Sie die folgenden Aktionen aus, um eine generische Zeichenfolge in einfache Anführungszeichen zu setzen:

    1. Ersetzen Sie eine beliebige Folge von Zeichen, die keine einfachen Anführungszeichen sind, durch die gleiche Folge, indem Sie einfache Anführungszeichen und abschließende Anführungszeichen hinzufügen: 'aaa' ==> ''aaa''

    2. Flucht mit einem Backslash jeden bereits existierenden Apostroph Zeichen: ' ==> \'
      Insbesondere''aaa'' ==> \''aaa'\'

  2. Führen Sie die folgenden Aktionen aus, um eine generische Zeichenfolge in doppelte Anführungszeichen zu setzen:

    1. Fügen Sie führende und nachfolgende doppelte Anführungszeichen hinzu: aaa ==> "aaa"

    2. Entfliehen Sie mit einem Backslash jedem Anführungszeichen und jedem Backslash-Zeichen: " ==> \", \ ==> \\

Einige Beispiele:

''aaa""bbb''ccc\\ddd''  ==>  \'\''aaa""bbb'\'\''ccc\\ddd'\'\'
                        ==>  "''aaa\"\"bbb''ccc\\\\ddd''"

Damit könnte Ihr Beispiel folgendermaßen erweitert werden:

#!/bin/sh

echo \''aaa'\'' "bbb"'
echo "'aaa' \"bbb\""

sudo su enzotib -c 'echo \'\'\''aaa'\''\'\'\'' "bbb"'\'
sudo su enzotib -c 'echo "'\''aaa'\'' \"bbb\""'

sudo su enzotib -c "echo \\''aaa'\\'' \"bbb\"'"
sudo su enzotib -c "echo \"'aaa' \\\"bbb\\\"\""
Enzotib
quelle
10

Einfaches Beispiel für das Entziehen von Anführungszeichen in der Shell:

$ echo 'abc'\''abc'
abc'abc
$ echo "abc"\""abc"
abc"abc

Dies geschieht, indem Sie bereits geöffnetes ( ') beenden , escape-Zeichen setzen ( \') und dann ein anderes öffnen ( ').

Alternative:

$ echo 'abc'"'"'abc'
abc'abc
$ echo "abc"'"'"abc"
abc"abc

Sie beenden das bereits geöffnete ( '), platzieren das Zitat in einem anderen Zitat ( "'") und öffnen dann ein anderes ( ').

Verwandte Themen: Wie vermeide ich einfache Anführungszeichen innerhalb von Zeichenfolgen in einfachen Anführungszeichen? bei stackoverflow SE

Kenorb
quelle
1

Die akzeptierte Antwort funktioniert für einfache (einstufige) Zitate:

$ echo $'\'single quote phrase\' "double quote phrase"'
'single quote phrase' "double quote phrase"

Damit der Befehl angezeigt wird, müssen Sie ihn zweimal zitieren.
Dieses Skript könnte die ganze Arbeit erledigen:

#!/bin/bash

quote () { 
    local quoted=${1//\'/\'\\\'\'};
    printf "'%s'" "$quoted"
}

read -r line <<-\_line_to_quote_
'single quote phrase' "double quote phrase"
_line_to_quote_

quote "$line"; echo
quote "echo $(quote "$line")"; echo

Führen Sie das Skript aus, um Folgendes zu erhalten:

$ script
''\''single quote phrase'\'' "double quote phrase"'
'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

Die erste Zeile funktioniert für einfaches Echo:

$ echo ''\''single quote phrase'\'' "double quote phrase"'
'single quote phrase' "double quote phrase"

Die zweite Zeile funktioniert für den Befehl in doppelten Anführungszeichen:

sudo su USER -c 'echo '\'''\''\'\'''\''single quote phrase'\''\'\'''\'' "double quote phrase"'\'''

quelle
-3

Echo "Ich bin ein Student" funktioniert nicht. Aber das Folgende funktioniert:

echo $ 'I \' ma student 'Aus der Manpage von bash:

Ein einfaches Anführungszeichen darf nicht zwischen einfachen Anführungszeichen stehen, auch wenn ein Backslash vorangestellt ist. .... Wörter der Form $ 'string' werden speziell behandelt. Das Wort wird zu einer Zeichenfolge erweitert, wobei mit einem Backslash versehene Zeichen gemäß dem ANSI C-Standard ersetzt werden.

Sarf
quelle
6
Dies fügt den vorhandenen Antworten nichts hinzu.
Jasonwryan