web-dev-qa-db-ja.com

さまざまなコマンドでのバックスラッシュの使用

私は、特定のコマンドでバックスラッシュがどのように使用されるかをよりよく理解しようとしています。特殊文字(echo 'that'\''s no moon'など)をエスケープするための使用法を理解していますが、他のコマンドからの出力は少し混乱しています。例えば:

rpm-qa rpmname\*

grep '\s/tmp' /etc/fstab

誰かが私のためにこれらを分解してくれませんか?また、あなたが知っているかもしれない他のどんな使い方にも興味があります。ありがとうございました!

4
user217282

バックスラッシュは、「次の文字に特別な意味を与えるのではなく、自分自身を表す」と言うためによく使用されます。バックスラッシュは次の文字を引用すると言います。この意味は、シェル構文を含む多くのプログラミング言語に存在します。たとえば、rpm-qa rpmname\*では、円記号によって*文字が引数でrpm-qaコマンドに渡されます。対照的に、rpm-qa rpmname*rpmname*rpmnameで始まる現在のディレクトリ内のファイル名のリストに置き換えます。 (一致するファイルがない場合、bashはrpmname*をそのままにします。デフォルトでは、zshは一致がないことを報告します。)

シェルは、文字を文字どおりに解釈する別の方法を提供します。つまり、文字を特別な方法で解釈するのではなく、それ自体を表すようにします。これが引用です。これは、文字のシーケンス全体の特別な意味を取り消します。引用符には次の2種類があります。単一引用符'は、次の単一引用符まですべての文字をそれ自身で表します。一方、二重引用符"は、いくつかの文字("$\および`)。 echo 'that'\''s no moon'では、echoコマンドは単一の引数を受け取ります。これはthatを連結したものです(リテラル文字列で書き込まれ、その中に特別な意味を持つ文字があったわけではありません)特定のケース)、'(バックスラッシュ-シングルクォートはそのシングルクォートの特別な意味を取り消すため、これは1つのシングルクォート文字に拡張されます)、およびs no moon(スペースは特別な意味を失います。引用符内:引数を区切るのではなく、引数の一部です)。

シェルでは、バックスラッシュに特別な意味がある場合、通常は次の文字を引用します。だが:

  • 単一引用符内では、バックスラッシュは特別な意味を持ちません。
  • 二重引用符内では、バックスラッシュは次の文字が"$\`の1つである場合にのみ引用します。それ以外の場合、バックスラッシュとそれに続く文字の両方が文字どおりに解釈されます。 "\a"は、2文字の文字列\aです。
  • ドル一重引用符リテラル内では、バックスラッシュは [〜#〜] c [〜#〜] の場合と同様に異なる意味を持っています。バックスラッシュの後に8進数字または特定の文字が続くと、文字を入力する別の方法が提供されます。これは、印刷できない文字の場合に便利です。たとえば、\nは小文字のN、"\n"はバックスラッシュ+ nですが、$'\n'は改行文字です。

grep '\s/tmp' /etc/fstabでは、単一引用符によってgrepが引数\s/tmpを受け取ります。この引数は 正規表現 です。正規表現には多くの構文バリアントがありますが、ほとんどは2つの標準 POSIX基本正規表現(BRE)および拡張正規表現(ERE) のいずれかに基づいています。 EREは、バックスラッシュの後に文字または数字以外の文字が続く文字を引用するという広く使用されている規則に従います。しかし、歴史的な理由により、BREでは、バックスラッシュが次の文字を特別なものにすることがあります。この場合、\sは、基本的な正規表現構文のGNU grep拡張機能であり、BREとEREの両方で使用でき、1つの空白文字を意味します。したがって、grep '\s/tmp' /etc/fstabは行をリストします。 /etc/fstabで、スペースまたはタブが前に付いた/tmpを含む.

そうです、バックスラッシュは文字をエスケープするために使用されるという一般的な慣習があります。その文字には特別な意味があり、リテラルにしたいのです。

# echo 'It\'s a string!'

上記の例では、アポストロフィを使用してリテラル文字列を区切りますが、文字列内にアポストロフィが必要なため、エスケープする必要があります。

もう1つのケースは、「通常の」文字に特別な意味を持たせる必要がある場合とは逆です。

# grep '\s/tmp' /etc/fstab

上記の例では、バックスラッシュはsが特別な意味を持ち、リテラルsではないことをgrepに伝えることです(RegEx空白スペース:スペース、タブ、改行、復帰、垂直タブ) )

つまり、文字に2つの可能な意味がある場合、それをエスケープして二次的な意味にします。

編集:

最初の例として:

rpm-qa rpmname\*

ここで*は特別な意味( 'rpmname'で始まるもの)を持っていますが、シェルがそれを拡張しようとするのを避けるために、エスケープしてコマンドrpmがリテラル*を取得し、それに応じて処理します。

これは文字列が何回も解釈され、文字列がいくつかのコマンドによって渡されるときに実際の苦労になる可能性があります。

1
Dalvenjia

私はあなたがbashかそのようなものを使っていると思います。

まず、bashが入力を評価する方法を理解する必要があります。 bashで使用できる特殊文字はたくさんあります。それらのいくつかは例えば_* ; ~ $_です

入力を入力すると、bashは本来あるべきすべての文字を置き換えようとします。たとえば、_$_記号で始まる変数。 _*_は、現在のディレクトリにあるすべてのファイル/ディレクトリに置き換えられます(pwdで決定)。

置換ステップが完了すると、bashは最終的に(fork()を使用して)指定したプログラムを実行します。

_\_は、指定された特殊文字を無視するようにbashに指示します:_\*_

1
J. Pee

\は、特殊文字のエスケープと正規表現のトリガーの両方に使用されます。

rpmコマンドは*をエスケープしています。この場合、機能的にはエスケープしないことと同じです。 RPMは*が無効なパッケージ文字であることを認識しているため、エスケープしても解釈されます。特殊文字のエスケープは、英数字以外のファイル名を処理する場合などによく使用されます。

2つのファイル(1つは「foo-biz-bar」という名前、もう1つは「foo * bar」という名前)を想定し、「foo * bar」だけを表示したいとします。以下の最初の結果は、エスケープされていない*がblobワイルドカードであるために発生します。

$ ls foo*bar
foo*bar foo-biz-bar
$ ls foo\*bar
foo*baz

grepの例の\sは、「空白」を意味する正規表現で、タブとスペースを意味します。

さらに読む

正規表現の完全なリストをオンラインで入手するのは困難ですが、 ここ から始めることができます。

私を大きく助けてくれた本は「Unix Shells by Example」でした。広範なsedgrep、およびawkの使用もすべてカバーされました。

1
Cory Ringdahl