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

bash: 特殊文字を含むコマンドライン引数を渡す方法

入力として正規表現を必要とするlinuxプログラムprogramを自分で書いたことがあります。

シェルでプログラムを呼び出して、その正規表現をコマンドライン引数としてプログラムに渡したいと思います(他のコマンドライン引数もあります)。典型的な正規表現は次のようになります。

[abc]\_[x|y]

残念ながら、bash[]|の文字はbashの特殊文字です。したがって、

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

を呼び出してもうまくいきません。何かエスケープ文字や引用符などを使って式を渡す方法はないでしょうか?

(program "[abc]\_[x|y] anotheragument"の呼び出しも、2つの引数を1つのものとして解釈しているため、うまくいきません)

回答 (8)

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

1.各特殊記号をバックスラッシュでエスケープする(\[abc\]_\[x\|y\]のように)か、 2. 引数全体をダブルクォートする("[abc]_[x|y]"のように)。

EDIT: ある が指摘しているように、dobleqouting は変数の展開やコマンドの置換を防ぎません。したがって、もしあなたの正規表現に bash がそれらの一つとして解釈できるものが含まれている場合は、代わりに シングルクォート を使用してください。

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

シングルクォーテーションを使用してください。シングルクォートを使用すると、どの文字も解釈されなくなります。

$ 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
'

シングルクォートを埋め込む必要がある場合、2つの解決策があります。

$ 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

man bash

引用符の仕組みには、エスケープ文字、シングルクォーテーション、ダブルクォーテーションの3つがあります。

引用符で囲まれていないバックスラッシュ ( ** ) は escape character です。これは、次の文字のリテラル値を保持します。もし\* ✿が現れ、バックスラッシュがそれ自体引用されていない場合、*** ✿は、行の続きとして扱われる(つまり、入力ストリームから取り除かれ、事実上無視される)。

単一引用符で文字を囲むことは、引用符内の各文字のリテラル値を保持する。単一引用符の間には、バックスラッシュが先行していても、単一引用符が発生することはありません。

二重引用符で囲む文字は、引用符内のすべての文字のリテラル値を保持しますが、$` , ** , and, when history expansion is enabled, **!. The characters $ and ` は二重引用符内で特別な意味を保持します。バックスラッシュは、以下のいずれかの文字の後に続く場合にのみ特別な意味を持ちます。$ , ` , , ** , または **<newline>。二重引用符は、二重引用符の前にバックスラッシュを付けることで、二重引用符の中に引用することができます。この機能を有効にすると、二重引用符の中の!がバックスラッシュでエスケープされない限り、履歴の展開が行われます。!の前のバックスラッシュは削除されません。

特別なパラメータ *@ は、二重引用符で囲まれている場合、特別な意味を持ちます(後述の PARAMETERS を参照)。

$‘ string 形式の単語は特別に扱われます。単語は string に展開され、バックスラッシュエスケープされた文字は ANSI C 標準で指定されているように置き換えられます。バックスラッシュエスケープシーケンスが存在する場合、以下のようにデコードされます。

**\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**  


展開された結果は、あたかもドル記号が存在しないかのように単一引用符で囲まれます。

ダブルクォートで囲まれた文字列の前にドル記号 ( **$"** _string_ **"** ) をつけると、文字列は現在のロケールに応じて翻訳されます。現在のロケールが **C** または **POSIX** の場合、ドル記号は無視されます。文字列が翻訳されて置換された場合は、ダブルクォートで置換されます。 **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

展開された結果は、あたかもドル記号が存在しないかのように単一引用符で囲まれます。

ダブルクォートで囲まれた文字列の前にドル記号 ( $” string ) をつけると、文字列は現在のロケールに応じて翻訳されます。現在のロケールが C または POSIX の場合、ドル記号は無視されます。文字列が翻訳されて置換された場合は、ダブルクォートで置換されます。

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

正規表現としては役に立たないかもしれませんが、文字列の中には Bash の変数名として解釈されるものがあります。このようなことが起こらないように、また展開されないようにするには、二重引用符ではなくシングルクォーテーションを使用してください。

program '[abc]_[x|y]' anotherargument
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

それぞれの引数は独立した引数として解釈されるように (引用符が必要な場合には) 個別に引用符で囲んでください。場合によっては配列を使用することもできます。

0x1& 0x1&

2
2
2
2010-07-14 12:57:29 +0000

特殊文字の前にバックスラッシュ ( `特殊文字の前にバックスラッシュ ( ) を使用すると、以下のようにエスケープすることができます。

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

そのパターンはどこから来るのか?それは固定されたものなのか、それともユーザーからのものなのか?ローカルシステム上でスクリプトを起動しているのはユーザなのか、それともリモートの誰かなのか?

シェルがデータを解釈しないようにするために、引用符を使ってデータを折り返しています。オプションは2つあります。

1.ダブルクォート。backticks は正規表現 (行末/バッファ) で有効な文字なので、変数に格納している場合を除いて、正規表現を保持するためにシングルクォートを使用したいと思うでしょう。信頼されていない人から任意のデータを取得する場合は、$' に置き換えてからシングルクォートで囲む必要があります。

'"'"' は、[abc]_[x|y] または x と一致させたいように見えますが、実際には 3 つの文字 y のうちの 1 つと一致していることに注意してください。角括弧は範囲内の文字にマッチし、範囲の場合はxy|のみ、否定の場合は先頭の-にマッチします。つまり、^はあなたが言いたいことかもしれませんし、括弧はシェルにとって特別な文字です。角括弧はシェルにとって特別な文字ではありません。二重角括弧 [abc]_(x|y) は特殊です。

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

エスケープしても問題なく動作するはずです:

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

関連する質問

6
10
11
7
12