it-swarm.com.de

Escape eine Variable zur Verwendung als Inhalt eines anderen Skripts

Diese Frage lautet nicht, wie ein ordnungsgemäß maskiertes String-Literal geschrieben wird. Ich konnte keine verwandte Frage finden, bei der es nicht darum geht, Variablen für den direkten Verbrauch innerhalb eines Skripts oder durch andere Programme zu umgehen.

Mein Ziel ist es, einem Skript zu ermöglichen, andere Skripte zu generieren. Dies liegt daran, dass die Aufgaben in den generierten Skripten auf einem anderen Computer zwischen 0 und n Mal ausgeführt werden und sich die Daten, aus denen sie generiert werden, möglicherweise ändern, bevor sie (erneut) ausgeführt werden Operationen direkt über ein Netzwerk funktionieren nicht.

Angesichts einer bekannten Variablen, die Sonderzeichen wie einfache Anführungszeichen enthalten kann, muss ich diese als vollständig maskiertes Zeichenfolgenliteral ausschreiben, z. Eine Variable foo mit bar'baz sollte im generierten Skript wie folgt angezeigt werden:

qux='bar'\''baz'

dies würde durch Anhängen von "qux=$foo_esc" an die anderen Skriptzeilen geschrieben. Ich habe es mit Perl so gemacht:

foo_esc="'`Perl -pe 's/('\'')/\\1\\\\\\1\\1/g' <<<"$foo"`'"

aber das scheint übertrieben.

Ich habe es nicht geschafft, es allein mit Bash zu machen. Ich habe viele Variationen davon ausprobiert:

foo_esc="'${file//\'/\'\\\'\'}'"
foo_esc="'${file//\'/'\\''}'"

aber entweder erscheinen zusätzliche Schrägstriche in der Ausgabe (wenn ich echo "$foo" mache) oder sie verursachen einen Syntaxfehler (erwarten weitere Eingaben, wenn sie über die Shell erfolgen).

22
Walf

Ich glaube, ich habe nicht RTFM. Es kann so gemacht werden:

q_mid=\'\\\'\'
foo_esc="'${foo//\'/$q_mid}'"

Dann echo "$foo_esc" gibt das erwartete 'bar'\''baz'


Wie ich es tatsächlich benutze, ist mit einer Funktion:

function esc_var {
    local mid_q=\'\\\'\'
    printf '%s' "'${1//\'/$mid_q}'"
}

...

foo_esc="`esc_var "$foo"`"

Ändern Sie dies, um das in Dejays Lösung integrierte printf zu verwenden:

function esc_vars {
    printf '%q' "[email protected]"
}
8
Walf

Bash hat eine Parametererweiterungsoption für genau diesen Fall :

${[email protected]} Die Erweiterung ist eine Zeichenfolge, die den Wert des Parameters angibt, der in einem Format angegeben ist, das als Eingabe wiederverwendet werden kann.

Also in diesem Fall:

foo_esc="${[email protected]}"

Dies wird in Bash 4.4 und höher unterstützt. Es gibt verschiedene Möglichkeiten für andere Erweiterungsformen und zum spezifischen Generieren vollständiger Zuweisungsanweisungen (@A).

33
Michael Homer

Bash bietet ein printf, das mit dem Formatbezeichner %q Eingebaut ist und die Shell-Escape-Funktion auch in älteren (<4.0) Versionen von Bash für Sie ausführt:

printf '[%q]\n' "Ne'er do well"
# Prints [Ne\'er\ do\ well]

printf '[%q]\n' 'Sneaky injection $( whoami ) `ls /root`'
# Prints [Sneaky\ injection\ \$\(\ whoami\ \)\ \`ls\ /root\`]

Dieser Trick kann auch verwendet werden, um Datenfelder von einer Funktion zurückzugeben:

function getData()
{
  printf '%q ' "He'll say hi" 'or `whoami`' 'and then $( byebye )'
}

declare -a DATA="( $( getData ) )"
printf 'DATA: [%q]\n' "${DATA[@]}"
# Prints:
# DATA: [He\'ll\ say\ hi]
# DATA: [or\ \`whoami\`]
# DATA: [and\ then\ \$\(\ byebye\ \)]

Beachten Sie, dass sich das integrierte Bash printf von dem Dienstprogramm printf unterscheidet, das mit den meisten Unix-ähnlichen Betriebssystemen geliefert wird. Wenn der Befehl printf aus irgendeinem Grund das Dienstprogramm anstelle des integrierten Dienstprogramms aufruft, können Sie stattdessen immer builtin printf Ausführen.

14
Dejay Clayton

Es gibt verschiedene Lösungen, um einen var-Wert anzugeben:

  1. alias
    In den meisten Shells (wo Alias ​​verfügbar ist) (außer csh, tcsh und wahrscheinlich anderen csh-ähnlichen):

    $ alias qux=bar\'baz
    $ alias qux
    qux='bar'\''baz'
    

    Ja, dies funktioniert in vielen sh-ähnlichen Schalen wie Dash oder Ash.

  2. einstellen
    Auch in den meisten Muscheln (wieder nicht csh):

    $ qux=bar\'baz
    $ set | grep '^qux='
    qux='bar'\''baz'
    
  3. setzen
    In einigen Shells (mindestens ksh, bash und zsh):

    $ qux=bar\'baz
    $ typeset -p qux
    typeset qux='bar'\''baz'             # this is zsh, quoting style may
                                         # be different for other shells.
    
  4. export
    Zuerst:

    export qux=bar\'baz
    

    Dann benutze:
    kshexport -p | grep 'qux='bashexport -p | grep 'qux='
    zshexport -p qux

  5. zitat
    Bashecho "${[email protected]}"
    zshecho "${(qq)qux}" # Es können ein bis vier Qs verwendet werden.

5
Isaac