it-swarm.com.de

Welche Zeichen müssen bei der Verwendung von Bash maskiert werden?

Gibt es eine umfassende Liste von Zeichen, die in Bash maskiert werden müssen? Kann es nur mit sed überprüft werden?

Insbesondere habe ich überprüft, ob % muss entkommen oder nicht. Ich habe es versucht

echo "h%h" | sed 's/%/i/g'

und hat gut funktioniert, ohne zu entkommen %. Bedeutet das % muss nicht entkommen werden? War dies ein guter Weg, um die Notwendigkeit zu überprüfen?

Und allgemeiner: Sind es die gleichen Zeichen, die in Shell und bash zu entkommen sind?

159
fedorqui

Es gibt zwei einfache und sichere Regeln, die nicht nur in sh, sondern auch in bash funktionieren.

1. Setzen Sie den gesamten String in einfache Anführungszeichen

Dies funktioniert für alle Zeichen außer für einfache Anführungszeichen. Um das einfache Anführungszeichen zu umgehen, schließen Sie das vorherige Anführungszeichen, fügen Sie das einfache Anführungszeichen ein und öffnen Sie das Anführungszeichen erneut.

'I'\''m a [email protected] $tring which ends in newline
'

sed Befehl: sed -e "s/'/'\\\\''/g; 1s/^/'/; \$s/\$/'/"

2. Entkomme jedem Buchstaben mit einem Backslash

Dies funktioniert für alle Zeichen außer Newline. Verwenden Sie für Zeilenumbrüche einfache oder doppelte Anführungszeichen. Leere Zeichenketten müssen noch behandelt werden - ersetzen durch ""

\I\'\m\ \a\ \s\@\f\e\ \$\t\r\i\n\g\ \w\h\i\c\h\ \e\n\d\s\ \i\n\ \n\e\w\l\i\n\e"
"

sed Befehl: sed -e 's/./\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'.

2b. Mehr lesbare Version von 2

Es gibt einen einfachen, sicheren Zeichensatz wie [a-zA-Z0-9,._+:@%/-], der nicht umgangen werden kann, um die Lesbarkeit zu verbessern

I\'m\ a\ [email protected]\ \$tring\ which\ ends\ in\ newline"
"

sed Befehl: LC_ALL=C sed -e 's/[^a-zA-Z0-9,[email protected]%/-]/\\&/g; 1{$s/^$/""/}; 1!s/^/"/; $!s/$/"/'.


Beachten Sie, dass man in einem sed-Programm nicht wissen kann, ob die letzte Eingabezeile mit einem Newline-Byte endet (außer wenn es leer ist). Das ist der Grund, warum beide obigen sed-Befehle davon ausgehen, dass dies nicht der Fall ist. Sie können einen zitierten Zeilenumbruch 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 von Bedeutung sind, funktioniert binär mit Ausnahme von NUL-Bytes (da Variablen mit C-Zeichenfolgen implementiert werden und als C-Zeichenfolgen, dh Programmargumente, verwendet werden sollen), Sie sollten jedoch zu einem "binären" Gebietsschema wie latin1 wechseln .


(Sie können die Regeln einfach validieren, indem Sie die POSIX-Spezifikation für sh lesen. Informationen zur Bash finden Sie im Referenzhandbuch, das mit @AustinPhillips verknüpft ist.)

219
Jo So

format, das als Shell-Eingabe wiederverwendet werden kann

Es gibt eine spezielleprintf -Formatanweisung (%q) für diese Art von Anfrage gebaut:

printf [-v var] format [Argumente]

 %q     causes printf to output the corresponding argument
        in a format that can be reused as Shell input.

Einige Beispiele:

read foo
Hello world
printf "%q\n" "$foo"
Hello\ world

printf "%q\n" $'Hello world!\n'
$'Hello world!\n'

Dies könnte auch durch Variablen verwendet werden:

printf -v var "%q" "$foo
"
echo "$var"
$'Hello world\n'

Schnelle Prüfung mit allen (128) ASCII-Bytes:

Beachten Sie, dass alle Bytes von 128 bis 255 maskiert werden müssen.

for i in {0..127} ;do
    printf -v var \\%o $i
    printf -v var $var
    printf -v res "%q" "$var"
    esc=E
    [ "$var" = "$res" ] && esc=-
    printf "%02X %s %-7s\n" $i $esc "$res"
done |
    column

Dies muss ungefähr so ​​aussehen:

00 E ''         1A E $'\032'    34 - 4          4E - N          68 - h      
01 E $'\001'    1B E $'\E'      35 - 5          4F - O          69 - i      
02 E $'\002'    1C E $'\034'    36 - 6          50 - P          6A - j      
03 E $'\003'    1D E $'\035'    37 - 7          51 - Q          6B - k      
04 E $'\004'    1E E $'\036'    38 - 8          52 - R          6C - l      
05 E $'\005'    1F E $'\037'    39 - 9          53 - S          6D - m      
06 E $'\006'    20 E \          3A - :          54 - T          6E - n      
07 E $'\a'      21 E \!         3B E \;         55 - U          6F - o      
08 E $'\b'      22 E \"         3C E \<         56 - V          70 - p      
09 E $'\t'      23 E \#         3D - =          57 - W          71 - q      
0A E $'\n'      24 E \$         3E E \>         58 - X          72 - r      
0B E $'\v'      25 - %          3F E \?         59 - Y          73 - s      
0C E $'\f'      26 E \&         40 - @          5A - Z          74 - t      
0D E $'\r'      27 E \'         41 - A          5B E \[         75 - u      
0E E $'\016'    28 E \(         42 - B          5C E \\         76 - v      
0F E $'\017'    29 E \)         43 - C          5D E \]         77 - w      
10 E $'\020'    2A E \*         44 - D          5E E \^         78 - x      
11 E $'\021'    2B - +          45 - E          5F - _          79 - y      
12 E $'\022'    2C E \,         46 - F          60 E \`         7A - z      
13 E $'\023'    2D - -          47 - G          61 - a          7B E \{     
14 E $'\024'    2E - .          48 - H          62 - b          7C E \|     
15 E $'\025'    2F - /          49 - I          63 - c          7D E \}     
16 E $'\026'    30 - 0          4A - J          64 - d          7E E \~     
17 E $'\027'    31 - 1          4B - K          65 - e          7F E $'\177'
18 E $'\030'    32 - 2          4C - L          66 - f      
19 E $'\031'    33 - 3          4D - M          67 - g      

Wenn das erste Feld ein Hexa-Wert des Bytes ist, enthält das zweite E, wenn das Zeichen maskiert werden muss, und das dritte Feld zeigt die maskierte Darstellung des Zeichens an.

Warum ,?

Sie könnten einige Zeichen sehen, die nicht immer maskiert werden müssen, wie ,, } und {.

Also nicht immer sondern irgendwann:

echo test 1, 2, 3 and 4,5.
test 1, 2, 3 and 4,5.

oder

echo test { 1, 2, 3 }
test { 1, 2, 3 }

aber Vorsicht:

echo test{1,2,3}
test1 test2 test3

echo test\ {1,2,3}
test 1 test 2 test 3

echo test\ {\ 1,\ 2,\ 3\ }
test  1 test  2 test  3

echo test\ {\ 1\,\ 2,\ 3\ }
test  1, 2 test  3 
43
F. Hauri

Um jemanden vor RTFM zu bewahren ... in bash:

Das Einschließen von Zeichen in doppelte Anführungszeichen behält den Literalwert aller Zeichen in den Anführungszeichen bei, mit Ausnahme von $, `, \ und, wenn die Verlaufserweiterung aktiviert ist, !.

... also, wenn Sie diesen (und natürlich dem Zitat selbst) entkommen, sind Sie wahrscheinlich in Ordnung.

Wenn Sie im Zweifelsfall konservativer vorgehen, sollten Sie vermeiden, Zeichen mit besonderer Bedeutung zu erhalten, indem Sie die Bezeichnerzeichen (dh ASCII Buchstaben, Zahlen oder '_'). Es ist sehr unwahrscheinlich, dass diese jemals (dh in einer seltsamen POSIX-artigen Shell) eine besondere Bedeutung haben und daher entkommen müssen.

30
Matthew

Verwendung der print '%q'Technik , wir können eine Schleife ausführen, um herauszufinden, welche Zeichen speziell sind:

#!/bin/bash
special=$'`[email protected]#$%^&*()-_+={}|[]\\;\':",.<>?/ '
for ((i=0; i < ${#special}; i++)); do
    char="${special:i:1}"
    printf -v q_char '%q' "$char"
    if [[ "$char" != "$q_char" ]]; then
        printf 'Yes - character %s needs to be escaped\n' "$char"
    else
        printf 'No - character %s does not need to be escaped\n' "$char"
    fi
done | sort

Es gibt diese Ausgabe:

No, character % does not need to be escaped
No, character + does not need to be escaped
No, character - does not need to be escaped
No, character . does not need to be escaped
No, character / does not need to be escaped
No, character : does not need to be escaped
No, character = does not need to be escaped
No, character @ does not need to be escaped
No, character _ does not need to be escaped
Yes, character   needs to be escaped
Yes, character ! needs to be escaped
Yes, character " needs to be escaped
Yes, character # needs to be escaped
Yes, character $ needs to be escaped
Yes, character & needs to be escaped
Yes, character ' needs to be escaped
Yes, character ( needs to be escaped
Yes, character ) needs to be escaped
Yes, character * needs to be escaped
Yes, character , needs to be escaped
Yes, character ; needs to be escaped
Yes, character < needs to be escaped
Yes, character > needs to be escaped
Yes, character ? needs to be escaped
Yes, character [ needs to be escaped
Yes, character \ needs to be escaped
Yes, character ] needs to be escaped
Yes, character ^ needs to be escaped
Yes, character ` needs to be escaped
Yes, character { needs to be escaped
Yes, character | needs to be escaped
Yes, character } needs to be escaped

Einige der Ergebnisse, wie , ein wenig misstrauisch aussehen. Wäre interessant, @ CharlesDuffys Inputs dazu zu bekommen.

21
codeforester

Zeichen, die maskiert werden müssen, unterscheiden sich in Bourne oder POSIX Shell von Bash. Im Allgemeinen ist (sehr) Bash eine Obermenge dieser Shells, also sollte alles, was Sie in Shell entkommen, in Bash entkommen.

Eine allgemeine Regel in Nizza wäre: "Wenn Sie Zweifel haben, entkommen Sie ihm". Aber einige Zeichen zu entkommen, gibt ihnen eine besondere Bedeutung, wie \n. Diese sind in der man bash Seiten unter Quoting und echo.

Wenn Sie keine alphanumerischen Zeichen verwenden, ist dies sicherer. Ich kenne keine einzige definitive 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 (History-Erweiterung) in Bash (und csh), jedoch nicht in Korn Shell. Sogar echo "Hello world!" gibt Probleme. Wenn Sie wie gewohnt einfache Anführungszeichen verwenden, wird die spezielle Bedeutung entfernt.

18
cdarke

Ich nehme an, dass Sie über Bash-Saiten sprechen. Es gibt verschiedene Arten von Zeichenfolgen, die unterschiedliche Anforderungen an die Flucht haben. z.B. Zeichenfolgen in einfachen Anführungszeichen unterscheiden sich von Zeichenfolgen in doppelten Anführungszeichen.

Die beste Referenz ist der Abschnitt Quoting des Bash-Handbuchs.

Es wird 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.

4
Austin Phillips

Ich habe festgestellt, dass Bash bei Verwendung der automatischen Vervollständigung einige Zeichen automatisch verliert.

Wenn Sie beispielsweise ein Verzeichnis mit dem Namen dir:A Haben, wird die Bash automatisch zu dir\:A Vervollständigt.

Auf dieser Grundlage habe ich einige Experimente mit Zeichen aus der Tabelle ASCII) durchgeführt und die folgenden Listen abgeleitet:

Zeichen, die bei der automatischen Vervollständigung ausgeblendet werden: (einschließlich Leerzeichen)

 !"$&'()*,:;<=>[email protected][\]^`{|}

Zeichen, die nicht entkommen:

#%+-.0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz~

(Ich habe / Ausgeschlossen, da es nicht in Verzeichnisnamen verwendet werden kann.)

3
yuri