web-dev-qa-db-ja.com

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

私は、入力として正規表現を必要とするLinuxプログラムprogramを自分で作成しました。

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

[abc]\_[x|y]

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

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

動作しません。なんらかのエスケープ文字や引用符などを使用して式を渡す方法はありますか?

program "[abc]\_[x|y] anotheragument"の呼び出しも、2つの引数を1つとして解釈するため、機能しません。)

33
Christian

あなたはどちらか

  1. 単一の特殊記号をバックスラッシュでエスケープする(\[abc\]_\[x\|y\]のように)または
  2. 引数全体を二重引用符で囲みます("[abc]_[x|y]"のように)。

EDIT:some が指摘したように、dobleqoutingは変数の展開やコマンドの置換を妨げません。したがって、正規表現にbashがそれらの1つとして解釈できるものがある場合は、代わりに 単一引用符を使用 を使用してください。

29
antichris

単一引用符を使用します。一重引用符は、どの文字も解釈されないようにします。

$ 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! ]
28
Flimm

man bash

エスケープ文字、一重引用符、二重引用符の3つの引用メカニズムがあります。

引用符で囲まれていないバックスラッシュ(\)は、エスケープ文字です。 <newline>を除いて、次の文字のリテラル値を保持します。 \ <newline>ペアが表示され、バックスラッシュ自体が引用されていない場合、\ <newline>は行の継続として扱われます(つまり、入力ストリームであり、事実上無視されます)。

文字を単一引用符で囲むと、引用符内の各文字のリテラル値が保持されます。バックスラッシュが前に付いている場合でも、単一引用符の間で単一引用符が発生しない場合があります。

文字を二重引用符で囲むと、$`\、および例外として、引用符内のすべての文字のリテラル値が保持されます。履歴の拡張が有効です。文字$および`は、二重引用符内で特別な意味を保持します。バックスラッシュは、次のいずれかの文字が続く場合にのみ特別な意味を保持します:$`"\ =、または<newline>。二重引用符は、バックスラッシュを前に付けることにより、二重引用符で囲むことができます。有効にすると、が出現しない限り、履歴の展開が実行されます二重引用符は円記号を使用してエスケープされますの前の円記号は削除されません。

特別なパラメーター*および@は、二重引用符で囲まれた場合に特別な意味を持ちます(以下の[〜#〜] parameters [〜#〜]を参照)。

形の言葉 $ 'ストリング 特別に扱われます。 Wordはstringに展開され、バックスラッシュでエスケープされた文字はANSI C標準で指定されているとおりに置き換えられます。バックスラッシュエスケープシーケンスが存在する場合は、次のようにデコードされます。

\ a     警告(ベル)
 \ b     バックスペース
 \ e\ E     エスケープ文字
 \ f     フォームフィード
 \ n     改行
 \ r     キャリッジリターン
 \ t     水平タブ
 \ v     垂直タブ
 \\     バックスラッシュ
 \ '     一重引用符
 「」     二重引用符
 \nnn   値が8進値である8ビット文字 nnn
(1から3桁)
 \バツHH   値が16進値である8ビット文字 HH
(1桁または2桁の16進数)
 \ uHHHH 値が
のUnicode(ISO/IEC 10646)文字、16進値 HHHH (1から4桁の16進数)
 \ UHHHHHHHH
値が
のUnicode(ISO/IEC 10646)文字。16進値 HHHHHHHH (1から8桁の16進数)
 \ cバツ    コントロール-バツ キャラクター

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

ドル記号が前に付いた二重引用符で囲まれた文字列($ "ストリング)は、現在のロケールに従って文字列を翻訳します。現在のロケールが[〜#〜] c [〜#〜]または[〜#〜] posix [〜#〜]の場合、ドル記号は無視されます。文字列が翻訳および置換される場合、置換は二重引用符で囲まれます。

6
Evan Carroll

バックスラッシュ(\)特殊文字の前で、次のようにエスケープします。

john @ awesome:〜#echo \&
&
2
John T

正規表現としては役に立たないかもしれませんが、一部の文字シーケンスは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
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument
1
Witek

パターンはどこから来たのですか?それは修正されたものですか、それともユーザーからのものですか?ローカルシステムでスクリプトを呼び出しているのはユーザーですか、それともリモートの誰かですか。

引用符を使用してデータをラップし、シェルがデータを解釈しないようにします。 2つのオプションがあります。

  1. いくつかの解釈を許可する二重引用符($ expandと `backticks`)
  2. 文字通りすべてを通過させる単一引用符

_$_は正規表現(行末/バッファー)で有効な文字であるため、変数に格納しない限り、単一引用符を使用して正規表現を保持することをお勧めします。信頼できない人から任意のデータを取得する場合は、_'_を_'"'"'_に置き換えてから、単一引用符で囲む必要があります。

_[abc]_[x|y]_は、xまたはyに一致するように見えますが、実際には、3つの文字_xy|_のいずれかに一致します。角括弧は、範囲の場合は_-_内の文字に一致し、否定の場合は先頭に_^_が一致します。したがって、[abc]_(x|y)はあなたが意図したものである可能性があり、括弧はシェルに特有の文字です。角括弧はシェルにとって特別なnotです。二重角括弧_[[ ... ]]_は特別です。

0
Phil P

それらをエスケープするとうまくいくはずです:

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