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


31

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

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

[abc]\_[x|y]

残念ながら、文字[]、および|に特殊文字ですbash。したがって、呼び出し

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

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

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

回答:


27

あなたはどちらか

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

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


4
bashのでは、ない二重引用符ではない変数拡大バイパス"$HOME"やパラメータ"${USER:-root}"のいずれかの形式で、コマンド置換を"$(date)""`date`"、算術展開"$((1 + 2))"、履歴展開"!!"やバックスラッシュはエスケープ"\\"。代わりに単一引用符を使用してください。bashマニュアルのマニュアルページの「引用」というタイトルのセクションを参照してください。
Flimm

25

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

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

その通りその通り。+1
アンチクリス

6

あたり man bash

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

引用符で囲まれていないバックスラッシュ(\)は エスケープ文字です。<newline>を除き、次の文字のリテラル値を保持します。場合は\ <改行>ペアが表示され、およびバックスラッシュは、それ自体ではなく、引用された\ <改行>行の継続(、それは入力ストリームから除去され、効果的に無視されている)として扱われます。

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

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

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

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

       \      警告(ベル)
        \ B      バックスペース
        \ E 
       \ E      エスケープ文字
        \ F      フォームフィード
        \ nは      改行
        \ r個の      キャリッジリターン
        \トン      水平タブ
        \ V      垂直タブ
        \\      バックスラッシュ
        \」      単一引用符
        \」      二重引用符
        \ NNN    値が8進数値nnnである8ビット文字
              (1〜3桁)
       \ x HH    値が16進数値HHである8ビット文字
              (1桁または2桁の16進数)
       \ u HHHH Unicode(ISO / IEC 10646)文字の値は
              16進値HHHH(1から4桁の16進数字)
        \ U HHHHHHHH
              値がUnicode(ISO / IEC 10646)文字
              16進値HHHHHHHH(1〜8進数字)
        \ C X     Aコントロール- X文字

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

二重引用符で囲まれた文字列の前にドル記号($ " string ")があると、現在のロケールに従って文字列が翻訳されます。現在のロケールがCまたはPOSIXの場合、ドル記号は無視されます。文字列が翻訳および置換される場合、置換は二重引用符で囲まれます。


2

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

john @ awesome:〜#エコー\&
&

2

正規表現としては役に立たないかもしれませんが、一部の文字シーケンスは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

1
program "[abc]_[x|y]"
program "[abc]_[x|y]" anotherargument

0

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

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

0

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

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

  1. ダブルクォート、まだいくらかの解釈を許可します($ expandと `backticks`)
  2. シングルクォート、文字通りすべてを通過させる

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

ことを注意[abc]_[x|y]あなたのようなルックスが一致したいxy、それは実際には3つのいずれかの文字にマッチいながら、xy|。角括弧は-、範囲内の文字と一致し、^否定の場合は先頭の文字と一致します。だから、[abc]_(x|y)あなたが意図したものかもしれません、そして括弧はシェルに特別な文字です。角括弧はシェルにとって特別なものではありません。二重角括弧[[ ... ]]は特別です。


これはここで最も正しい答えの1つです(特にに置き換えるための指示に感謝'します'"'"')が、まだ正しくありません。[シェルの特殊文字です。パス拡張を行うときにワイルドカードで使用されます(シェルは引用符で囲まれていないすべての処理を行います)。
ジャパレセク

変数の添え字付けやグロビングなど、一部のコンテキストでは特別ですが、入力foo=a[b]echo $fooてから文字列を引用符で囲む必要がないことがわかります。あなたは正しい、私は短すぎました。
フィルP

運が悪い場合abは、現在のディレクトリにファイルがあり、その後でfooabなくが含まれますa[b]。あなたの角括弧を引用してください、人々。
クラック

(明確にするために、引用を行います(元の答えが明確になったので、引用することを求めていた場所です)。この主張は私を驚かせたので、テストしました。zshやbashには当てはまりませんが、BSD / bin / shには当てはまります。これはPOSIXに反するものであり、非標準の動作であるため、処理するには引用する必要があります。zshでは、setopt glob_assignこの動作も有効にできるため、引用が最も安全な答えです。
フィルP
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.