Gibt es eine umfassende Liste von Zeichen, die in Bash maskiert werden müssen? Kann es nur mit überprüft werden sed
?
Insbesondere habe ich geprüft, ob %
entkommen muss oder nicht. Ich habe es versucht
echo "h%h" | sed 's/%/i/g'
und funktionierte gut, ohne zu entkommen %
. Bedeutet das, %
dass man nicht entkommen muss? War dies ein guter Weg, um die Notwendigkeit zu überprüfen?
Und allgemeiner: sie sind die gleichen Zeichen in zu entkommen shell
und bash
?
Antworten:
Es gibt zwei einfache und sichere Regeln, die nicht nur funktionieren,
sh
sondern auchbash
.1. Setzen Sie die gesamte Zeichenfolge in einfache Anführungszeichen
Dies funktioniert für alle Zeichen außer Anführungszeichen. Um dem einfachen Anführungszeichen zu entkommen, schließen Sie das Angebot davor, fügen Sie das einfache Anführungszeichen ein und öffnen Sie das Angebot erneut.
sed Befehl:
sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"
2. Entkomme jedem Zeichen mit einem Backslash
Dies funktioniert für alle Zeichen außer Zeilenumbruch. Verwenden Sie für Zeilenumbrüche einfache oder doppelte Anführungszeichen. Leere Zeichenfolgen müssen noch behandelt werden - ersetzen durch
""
sed Befehl :
sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.2b. Lesbarere Version von 2
Es gibt eine einfache und sichere Reihe von Zeichen,
[a-zA-Z0-9,._+:@%/-]
die nicht entfernt werden können, um die Lesbarkeit zu verbessernsed Befehl :
LC_ALL=C sed -e 's/[^a-zA-Z0-9,._+@%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'
.Beachten Sie, dass in einem sed-Programm nicht bekannt ist, ob die letzte Eingabezeile mit einem Zeilenumbruchbyte endet (außer wenn es leer ist). Aus diesem Grund gehen beide oben genannten sed-Befehle davon aus, dass dies nicht der Fall ist. Sie können eine zitierte neue Zeile manuell hinzufügen.
Beachten Sie, dass Shell-Variablen nur für Text im POSIX-Sinne definiert sind. Die Verarbeitung von Binärdaten ist nicht definiert. Für die Implementierungen, die wichtig sind, funktioniert Binär mit Ausnahme von NUL-Bytes (da Variablen mit C-Zeichenfolgen implementiert sind und als C-Zeichenfolgen, nämlich Programmargumente, verwendet werden sollen). Sie sollten jedoch zu einem "binären" Gebietsschema wie latin1 wechseln .
(Sie können die Regeln einfach
sh
überprüfen, indem Sie die POSIX-Spezifikation für lesen . Informationen zu Bash finden Sie im Referenzhandbuch, das mit @AustinPhillips verknüpft ist.)quelle
sed
, erfordert jedochbash
.Format, das als Shell-Eingabe wiederverwendet werden kann
Für diese Art von Anfrage gibt es eine spezielle
printf
Format-Direktive (%q
):Einige Beispiele:
Dies könnte auch durch Variablen verwendet werden:
Schnelle Überprüfung mit allen (128) ASCII-Bytes:
Beachten Sie, dass alle Bytes von 128 bis 255 maskiert werden müssen.
Dies muss so etwas wie Folgendes rendern:
Wenn das erste Feld der Hexa-Wert des Bytes ist, enthält das zweite Feld,
E
wenn ein Zeichen maskiert werden muss, und das dritte Feld zeigt die maskierte Darstellung des Zeichens.Warum
,
?Sie könnten einige Zeichen sehen, die nicht immer maskiert werden müssen, wie
,
,}
und{
.Also nicht immer aber irgendwann :
oder
aber Sorge:
quelle
subprocess.Popen(['bash', '-c', 'printf "%q\0" "$@"', '_', arbitrary_string], stdin=subprocess.PIPE, stdout=subprocess.PIPE).communicate()
Sie eine ordnungsgemäß in Shell zitierte Version vonarbitrary_string
.%q
war lange Zeit kaputt - Wenn mein Verstand mir gute Dienste leistet, wurde 2013 ein Fehler behoben (der aber möglicherweise immer noch kaputt sein wird), nachdem er ~ 10 Jahre lang kaputt war. Verlassen Sie sich also nicht darauf.shlex.quote()
(> = 3.3,pipes.quote()
- undokumentiert - für ältere Versionen) natürlich auch die Aufgabe und erstellt eine besser lesbare Version (Hinzufügen von Anführungszeichen und Escapezeichen, falls erforderlich) der meisten Zeichenfolgen. ohne die Notwendigkeit, eine Shell zu spawnen.,
. Ich war überrascht zu erfahren, dass eingebauter Bashprintf -- %q ','
gibt\,
, aber/usr/bin/printf -- %q ','
gibt,
(nicht entführt). Das Gleiche gilt für andere Zeichen:{
,|
,}
,~
.Um jemand anderem vor RTFM zu bewahren ... in Bash :
... also, wenn Sie diesen entkommen (und natürlich dem Zitat selbst), sind Sie wahrscheinlich in Ordnung.
Wenn Sie einen konservativeren Ansatz wählen, bei dem Sie Zweifel haben, sollten Sie es vermeiden, stattdessen Zeichen mit besonderer Bedeutung zu erhalten, indem Sie nicht den Bezeichnern (dh ASCII-Buchstaben, Zahlen oder '_') entkommen. Es ist sehr unwahrscheinlich, dass diese jemals (dh in einer seltsamen POSIX-ähnlichen Shell) eine besondere Bedeutung haben und daher entkommen müssen.
quelle
Mit dieser
print '%q'
Technik können wir eine Schleife ausführen, um herauszufinden, welche Zeichen etwas Besonderes sind:Es gibt diese Ausgabe:
Einige der Ergebnisse
,
sehen ein wenig verdächtig aus. Es wäre interessant, @ CharlesDuffys Beiträge dazu zu erhalten.quelle
,
um im letzten Absatz meiner Antwort%q
nicht wissen, wo in der Shell Sie das Zeichen verwenden möchten, sodass alle Zeichen ausgeblendet werden, die in einem möglichen Shell-Kontext eine besondere Bedeutung haben können.,
selbst hat keine besondere Bedeutung für sie Shell, aber wie @ F.Hauri in seiner Antwort hervorgehoben hat, hat es eine besondere Bedeutung innerhalb der Klammererweiterung{...}
: gnu.org/savannah-checkouts/gnu/bash/manual/… Das ist wie! Dies erfordert auch nur eine Erweiterung in bestimmten Situationen, nicht im Allgemeinen: Funktioniertecho Hello World!
einwandfrei, schlägtecho test!test
jedoch fehl.Zeichen, die maskiert werden müssen, unterscheiden sich in der Bourne- oder POSIX-Shell von Bash. Im Allgemeinen ist (sehr) Bash eine Obermenge dieser Muscheln, daher sollte alles, in dem Sie entkommen
shell
, in Bash entkommen.Eine nette allgemeine Regel wäre "wenn Sie Zweifel haben, entkommen Sie ihr". Aber einigen Charakteren zu entkommen, gibt ihnen eine besondere Bedeutung, wie z
\n
. Diese sind auf denman bash
Seiten unterQuoting
und aufgeführtecho
.Ansonsten entkomme jedem Zeichen, das nicht alphanumerisch ist, es ist sicherer. Ich kenne keine einzige endgültige Liste.
Die Manpages listen sie alle irgendwo auf, aber nicht an einem Ort. Lerne die Sprache, das ist der Weg, um sicher zu sein.
Eine, die mich erwischt hat, ist
!
. Dies ist ein Sonderzeichen (Geschichtserweiterung) in Bash (und csh), jedoch nicht in Korn Shell. Auchecho "Hello world!"
gibt Probleme. Wenn Sie wie gewohnt einfache Anführungszeichen verwenden, wird die spezielle Bedeutung entfernt.quelle
sed
gut genug ist, um zu sehen, ob es entkommen muss. Danke für deine Antwort!sed
ist nicht erforderlich, Sie können mit fast allem überprüfen.sed
ist nicht das Problem,bash
ist. In einfachen Anführungszeichen gibt es keine Sonderzeichen (außer einfache Anführungszeichen). Sie können dort nicht einmal Zeichen maskieren. Einsed
Befehl sollte normalerweise in einfachen Anführungszeichen stehen, da RE-Metazeichen zu viele Überlappungen mit Shell-Metazeichen aufweisen, um sicher zu sein. Die Ausnahme ist das Einbetten von Shell-Variablen, was sorgfältig durchgeführt werden muss.echo
. Wenn Sie herausholen, was Sie eingegeben haben, muss es nicht entkommen. :)Ich nehme an, dass Sie über Bash-Strings sprechen. Es gibt verschiedene Arten von Zeichenfolgen, für deren Escape unterschiedliche Anforderungen gelten. z.B. Zeichenfolgen in einfachen Anführungszeichen unterscheiden sich von Zeichenfolgen in doppelten Anführungszeichen.
Die beste Referenz ist der Abschnitt " Zitate " des Bash-Handbuchs.
Es erklärt, welche Charaktere entkommen müssen. Beachten Sie, dass einige Zeichen möglicherweise maskiert werden müssen, je nachdem, welche Optionen aktiviert sind, z. B. die Verlaufserweiterung.
quelle
Ich habe festgestellt, dass Bash bei Verwendung der automatischen Vervollständigung automatisch einigen Zeichen entgeht.
Wenn Sie beispielsweise ein Verzeichnis mit dem Namen haben
dir:A
, wird bash automatisch in vervollständigtdir\:A
Auf diese Weise habe ich einige Experimente mit Zeichen der ASCII-Tabelle durchgeführt und die folgenden Listen abgeleitet:
Zeichen, die beim automatischen Vervollständigen ausgeblendet werden : (einschließlich Leerzeichen)
Charaktere, die schlagen, entkommen nicht :
(Ich habe ausgeschlossen
/
, da es nicht in Verzeichnisnamen verwendet werden kann)quelle
printf %q
geändert werden und welche nicht, wenn sie als Argument übergeben werden - idealerweise durch den gesamten Zeichensatz.