A=\"\" grep $A が grep "" のように動作しないのはなぜですか?

A=\"\" grep $A が grep "" のように動作しないのはなぜですか?

私はLinuxでbashを使用しています。

$ A=\"\"
$ grep $A
nomatch
""
""                         <- (returned by grep)
$ grep ""
imatcheverything
imatcheverything           <- (returned by grep)

grep $A私はそのように行動すると予想されたgrep ""。文字通り一致するのはなぜですか""grepたとえば、(私が知っている限り)シェルgrep \\\\は最初にシェルを見てからgrep \\。行が含まれています\

私はこれがシェルが変数を置き換えて引用符を見る順序に関連していると思います。この動作は、変数置換フェーズの前にシェルが引用符を削除した場合に説明できます。


無関係なメモでは、私は比較的複雑な正規表現(書き込みではなく読み取り、理想的には「この正規表現の機能は何ですか?」と尋ねること)を持つリソースを探しており、BREまたはEREが望ましいです。

答え1

Bashは引数拡張後の引用符を評価しません。拡張値のみ処理噴射そしてファイル名拡張子変数を引用符で囲まないと、引用符は再解釈されなくなります。 IFSやglob以外の値と同様に、「単語」の一部になります。あなたの例では、Bashは""単語分割やglobパターンではないので、引数をgrepにそのまま渡します。

答え2

$ A = \"\"
$ grep $A

Bashでは、等号の周りにスペースがなく、その前にもスペースがなく、後にもスペースがありません。

$ A=\"\"
$ grep $A

答え3

grep ""空の文字列引数を使用してgrepを呼び出します。

grep $A(つまりgrep \"\"、実際には2つの二重引用符である1つの引数でgrepを呼び出します。

シェルがコマンドに送信する内容を知りたい場合は、以下のような小さなスクリプトを使用して理解できます。

#!/usr/bin/python3

import sys

args = sys.argv[1:] #skip the first one which is the name of the cmd

print(f"Number of args: {len(args)}")

for index, arg in enumerate(args, start=1):
    print(f"Arg {index}: Length: {len(arg)}")
    for char in arg:
        print(f"{ord(char)} {char}")

例1:

❯ ./showargs.py ""
Number of args: 1
Arg 1: Length: 0

例2:

❯ A=\"\"
❯ ./showargs.py $A  
Number of args: 1
Arg 1: Length: 2
34 "
34 "

例3:

❯ ./showargs.py foo \\\\
Number of args: 2
Arg 1: Length: 3
102 f
111 o
111 o
Arg 2: Length: 2
92 \
92 \

関連情報