私は、特定のコマンドでバックスラッシュがどのように使用されるかをよりよく理解しようとしています。特殊文字(echo 'that'\''s no moon'
など)をエスケープするための使用法を理解していますが、他のコマンドからの出力は少し混乱しています。例えば:
rpm-qa rpmname\*
grep '\s/tmp' /etc/fstab
誰かが私のためにこれらを分解してくれませんか?また、あなたが知っているかもしれない他のどんな使い方にも興味があります。ありがとうございました!
バックスラッシュは、「次の文字に特別な意味を与えるのではなく、自分自身を表す」と言うためによく使用されます。バックスラッシュは次の文字を引用すると言います。この意味は、シェル構文を含む多くのプログラミング言語に存在します。たとえば、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
です。\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
がリテラル*
を取得し、それに応じて処理します。
これは文字列が何回も解釈され、文字列がいくつかのコマンドによって渡されるときに実際の苦労になる可能性があります。
私はあなたがbashかそのようなものを使っていると思います。
まず、bashが入力を評価する方法を理解する必要があります。 bashで使用できる特殊文字はたくさんあります。それらのいくつかは例えば_* ; ~ $
_です
入力を入力すると、bashは本来あるべきすべての文字を置き換えようとします。たとえば、_$
_記号で始まる変数。 _*
_は、現在のディレクトリにあるすべてのファイル/ディレクトリに置き換えられます(pwd
で決定)。
置換ステップが完了すると、bashは最終的に(fork()
を使用して)指定したプログラムを実行します。
_\
_は、指定された特殊文字を無視するようにbashに指示します:_\*
_
\
は、特殊文字のエスケープと正規表現のトリガーの両方に使用されます。
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」でした。広範なsed
、grep
、およびawk
の使用もすべてカバーされました。