2010-07-14 12:51:58 +0000 2010-07-14 12:51:58 +0000
32
32

bash: Übergabe von Kommandozeilenargumenten mit Sonderzeichen

Ich habe mir ein Linux-Programm program geschrieben, das einen regulären Ausdruck als Eingabe benötigt.

Ich möchte das Programm in der Shell bash aufrufen und diesen regulären Ausdruck als Kommandozeilenargument an das Programm übergeben (es gibt auch andere Kommandozeilenargumente). Ein typischer regulärer Ausdruck sieht aus wie

[abc]\_[x|y]

Leider sind die Zeichen [, ] und | Sonderzeichen in bash. Daher funktioniert der Aufruf von

program [abc]\_[x|y] anotheragument

nicht. Gibt es eine Möglichkeit, den Ausdruck mit einer Art von Escape-Zeichen oder Anführungszeichen usw. zu übergeben?

(Der Aufruf von program "[abc]\_[x|y] anotheragument" funktioniert auch nicht, da er die beiden Argumente als eins interpretiert).

Antworten (8)

29
29
29
2010-07-14 12:59:46 +0000

Sie können entweder

  1. jedes einzelne Sonderzeichen mit einem Backslash (wie in \[abc\]_\[x\|y\]) entwerten oder
  2. Das gesamte Argument in Anführungszeichen setzen (wie in "[abc]_[x|y]").

EDIT: Wie einige festgestellt haben, verhindert die doppelte Anführungszeichengebung weder die Variablenexpansion noch die Befehlssubstitution. Wenn Ihre Regex also etwas enthält, das von der Bash als eines dieser Dinge interpretiert werden kann, verwenden Sie stattdessen einfache Anführungszeichen .

28
28
28
2011-10-21 12:19:50 +0000

Verwenden Sie einfache Anführungszeichen. Einfache Anführungszeichen stellen sicher, dass keines der Zeichen interpretiert wird.

$ printf %s 'spaces are not interpreted away
neither are new lines
nor variable names $TESTING
nor square brackets [TESTING]
nor pipe characters or redirection symbols | > <
nor the semicolon ;
nor backslashes \a \b \c \
the only thing that does not work is the single quote itself
'

Es gibt zwei Lösungen, wenn Sie ein einfaches Anführungszeichen einbetten müssen:

$ printf '%s\n' '[Don'"'"'t worry, be happy!]'
[Don't worry, be happy!]
$ printf '%s\n' '[Don''t worry, be happy!]'
[Don't worry, be happy!]
6
6
6
2010-07-15 06:09:18 +0000

Per man bash

Es gibt drei Quoting-Mechanismen: das escape-Zeichen, einfache Anführungszeichen und doppelte Anführungszeichen.

Ein nicht in Anführungszeichen gesetzter Backslash ( ** ) ist das escape-Zeichen. Es bewahrt den literalen Wert des nächsten Zeichens, das folgt, mit Ausnahme von <Newline>. Wenn ein ** <newline>-Paar erscheint und der Backslash selbst nicht in Anführungszeichen steht, wird der ** <newline> als Zeilenfortsetzung behandelt (d. h. er wird aus dem Eingabestrom entfernt und effektiv ignoriert).

Durch das Einschließen von Zeichen in einfache Anführungszeichen bleibt der literale Wert jedes Zeichens innerhalb der Anführungszeichen erhalten. Ein einfaches Anführungszeichen darf nicht zwischen einfachen Anführungszeichen stehen, auch wenn ein umgekehrter Schrägstrich vorangestellt ist.

Das Einschließen von Zeichen in doppelten Anführungszeichen behält den literalen Wert aller Zeichen innerhalb der Anführungszeichen bei, mit Ausnahme von $ , ` , ** , and, when history expansion is enabled, **!. The characters $ and `, die ihre besondere Bedeutung innerhalb von doppelten Anführungszeichen behalten. Der Backslash behält seine besondere Bedeutung nur, wenn er von einem der folgenden Zeichen gefolgt wird: $ , ` , , ** , oder **<newline>. Ein doppeltes Anführungszeichen kann innerhalb von doppelten Anführungszeichen zitiert werden, indem ihm ein umgekehrter Schrägstrich vorangestellt wird. Wenn diese Option aktiviert ist, wird die Historienexpansion durchgeführt, es sei denn, ein !, der in doppelten Anführungszeichen erscheint, wird mit einem Backslash escaped. Der Backslash vor dem ! wird nicht entfernt.

Die speziellen Parameter * und @ haben eine besondere Bedeutung, wenn sie in doppelten Anführungszeichen stehen (siehe PARAMETER unten).

Wörter der Form $‘ string werden speziell behandelt. Das Wort wird zu string expandiert, wobei Zeichen mit Backslash-Escape-Sequenzen gemäß dem ANSI C-Standard ersetzt werden. Backslash-Escape-Sequenzen, falls vorhanden, werden 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**  

Das expandierte Ergebnis steht in einfachen Anführungszeichen, als ob das Dollarzeichen nicht vorhanden gewesen wäre. 

Eine Zeichenkette in doppelten Anführungszeichen, der ein Dollarzeichen ( **$"** _string_ **"** ) vorangestellt ist, bewirkt, dass die Zeichenkette entsprechend dem aktuellen Gebietsschema übersetzt wird. Wenn das aktuelle Gebietsschema **C** oder **POSIX** ist, wird das Dollarzeichen ignoriert. Wenn die Zeichenfolge übersetzt und ersetzt wird, wird die Ersetzung in Anführungszeichen gesetzt. **single quote** \" **double quote** \**_nnn_ the eight-bit character whose value is the octal value _nnn_ (one to three digits)**\x**_HH_ the eight-bit character whose value is the hexadecimal value _HH_ (one or two hex digits)**\u**_HHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHH_ (one to four hex digits)**\U**_HHHHHHHH_ the Unicode (ISO/IEC 10646) character whose value is the hexadecimal value _HHHHHHHH_ (one to eight hex digits)**\c**_x_ a control-_x_ character

Das expandierte Ergebnis steht in einfachen Anführungszeichen, als ob das Dollarzeichen nicht vorhanden gewesen wäre.

Eine Zeichenkette in doppelten Anführungszeichen, der ein Dollarzeichen ( $” string ) vorangestellt ist, bewirkt, dass die Zeichenkette entsprechend dem aktuellen Gebietsschema übersetzt wird. Wenn das aktuelle Gebietsschema C oder POSIX ist, wird das Dollarzeichen ignoriert. Wenn die Zeichenfolge übersetzt und ersetzt wird, wird die Ersetzung in Anführungszeichen gesetzt.

2
2
2
2010-07-15 02:11:13 +0000

Auch wenn es als Regex nicht sinnvoll ist, können einige Zeichenfolgen als Bash-Variablennamen interpretiert werden. Um dies zu verhindern und zu vermeiden, dass sie erweitert werden, verwenden Sie einfache Anführungszeichen anstelle von doppelten Anführungszeichen:

program '[abc]_[x|y]' anotherargument

Setzen Sie jedes Argument separat in Anführungszeichen (falls sie Anführungszeichen benötigen), damit sie als unabhängige Argumente interpretiert werden. Sie können in einigen Fällen auch Arrays verwenden:

param_array=('[abc]_[x|y]' anotherargument) # create an array
param_array+=(yetanother) # append another element to the array
program "${param_array[@]}" # use the array elements as arguments to program
2
2
2
2010-07-14 12:57:29 +0000

Sie können einen Backslash ( `Sie können einen Backslash ( ) vor Sonderzeichen verwenden, um diese wie folgt zu entschlüsseln:

john@awesome:~ # echo 0x1& &
1
1
1
2010-07-14 12:56:05 +0000
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
0
0
0
2010-07-15 07:18:57 +0000

Woher kommt das Muster? Ist es festgelegt oder von einem Benutzer? Ist es der Benutzer, der das Skript auf dem lokalen System aufruft, oder jemand von außerhalb?

Sie verwenden Anführungszeichen, um Daten einzuschließen, damit die Shell sie nicht interpretieren kann. Es gibt zwei Möglichkeiten:

  1. doppelte Anführungszeichen, die noch eine gewisse Interpretation zulassen ($expand und backticks)
  2. Einfache Anführungszeichen, die alles buchstäblich durchlassen

Da $ ein gültiges Zeichen in Regexps ist (Zeilenende/Puffer), möchten Sie wahrscheinlich einfache Anführungszeichen verwenden, um den Regexp zu halten, es sei denn, Sie speichern ihn in einer Variablen. Wenn Sie beliebige Daten von jemandem nehmen, dem Sie nicht vertrauen, müssen Sie ' durch '"'"' ersetzen und dann in einfache Anführungszeichen einschließen.

Beachten Sie, dass [abc]_[x|y] so aussieht, als ob Sie mit x oder y übereinstimmen wollen, während es tatsächlich mit einem der drei Zeichen xy| übereinstimmt. Die eckigen Klammern passen auf die Zeichen innerhalb und nur auf - für Bereiche und ein ^ am Anfang für die Negation. Also, [abc]_(x|y) könnte das sein, was Sie meinten, und die Klammern sind die Zeichen, die speziell für Shell sind. Eckige Klammern sind nicht speziell für Shell, es sieht nur so aus, als ob sie es wären. Doppelt-quadratische Klammern [[...]] sind speziell.

0
0
0
2010-07-14 12:57:13 +0000

Das Escapen sollte problemlos funktionieren:

programm \[abc\]_\[x\|y\]