grep appleファイルとgrep "apple"ファイルの違いは何ですか?


22

違いは何であるgrep apple fileとはgrep "apple" file?引用符を付けるとどうなりますか?どちらも動作しているように見え、まったく同じことを行います(同じ行を表示します)。

回答:


45

引用符は、シェルが特殊文字とみなし、構文上の意味を持つ文字に影響を与えます。この例では、このappleような文字が含まれていないため、違いはありません。

しかし、別の例を考えてみますgrep apple tree file単語を検索しますappleファイルにtreeしてfile、一方grep "apple tree" fileの単語を検索するapple treeファイルにfile。引用符は、bashに、単語スペースが"apple tree"新しいパラメーターを開始するのではなく、現在のパラメーターの一部となることを示します。grep apple\ tree fileなぜなら\、次の文字の特別な意味を無視して文字通りに扱うようにbashに指示するからです。


2
これはワイルドカードでも表示されます。もしそうならgrep a*b equations.txt、それは検索されますa*bで始まる現在のディレクトリにファイルがある場合を除き、aとbで終わる、(理由は(BA)のshは、コマンドラインでファイル名を拡大します)その場合に呼び出されますグレップさまざまなパラメーターを入力すると、結果が異なります。これは通常、findの問題find . -name *.txtです。現在のディレクトリにtxtファイルがある場合、次のようなコマンドは予期しない動作を引き起こすためです。この場合、引用符を使用することをお勧めします。
SztupY

4
もう1つの重要な点は、二重引用符(")と単一引用符(')の違いです。単一引用符は、などの特定の文字の解釈を防ぎ$ますが、二重引用符は解釈を許可します。例えば、grep '${USER}'テキストを探します${USER}一方、grep "${USER}"変数があること、テキストを探しますUSER含まれている(例えばjohnstacen)。
水田ランダウ

23

コマンドラインで使用した場合、二重引用符で評価でき、単一引用符で評価できず、引用符でワイルドカードを展開できません。考案された例として:

[user@work test]$ ls .
A.txt B.txt C.txt D.cpp

# The following is the same as writing echo 'A.txt B.txt C.txt D.cpp'
[user@work test]$ echo *
A.txt B.txt C.txt D.cpp

[user@work test]$ echo "*"
*

[user@work test]$ echo '*'
*

# The following is the same as writing echo 'A.txt B.txt C.txt'
[user@work test]$ echo *.txt
A.txt B.txt C.txt

[user@work test]$ echo "*.txt"
*.txt

[user@work test]$ echo '*.txt'
*.txt

[user@work test]$ myname=is Fred; echo $myname
bash: Fred: command not found

[user@work test]$ myname=is\ Fred; echo $myname
is Fred

[user@work test]$ myname="is Fred"; echo $myname
is Fred

[user@work test]$ myname='is Fred'; echo $myname
is Fred

引用の仕組みを理解することは、Bashを理解する上で極めて重要です。例えば:

# for will operate on each file name separately (like an array), looping 3 times.
[user@work test]$ for f in $(echo *txt); do echo "$f"; done;
A.txt
B.txt
C.txt

# for will see only the string, 'A.txt B.txt C.txt' and loop just once.
[user@work test]$ for f in "$(echo *txt)"; do echo "$f"; done;
A.txt B.txt C.txt

# this just returns the string - it can't be evaluated in single quotes.
[user@work test]$ for f in '$(echo *txt)'; do echo "$f"; done;
$(echo *txt)

単一引用符を使用して、変数を介してコマンドを渡すことができます。単一引用符は評価を妨げます。二重引用符が評価されます。

# This returns three distinct elements, like an array.
[user@work test]$ echo='echo *.txt'; echo $($echo)
A.txt B.txt C.txt

# This returns what looks like three elements, but it is actually a single string.
[user@work test]$ echo='echo *.txt'; echo "$($echo)"
A.txt B.txt C.txt

# This cannot be evaluated, so it returns whatever is between quotes, literally.
[user@work test]$ echo='echo *.txt'; echo '$($echo)'
$($echo)

ダブルクォート内でシングルクォートを使用でき、ダブルクォート内でダブルクォートを使用できますが、シングルクォート内のダブルクォートは(エスケープせずに)行われるべきではなく、文字通りに解釈されます。単一引用符内の単一引用符は(エスケープせずに)実行しないでください。

Bashを効果的に使用するには、引用符を完全に理解する必要があります。非常に重要です!

一般的なルールとして、Bashで要素(配列など)に何かを展開する場合は引用符を使用せず、変更しないリテラル文字列には単一引用符を使用し、変数には二重引用符を自由に使用しますあらゆるタイプの文字列を返す可能性があります。これは、スペースと特殊文字が確実に保持されるようにするためです。


二重引用符の中で二重引用符をどのように使用しますか?それはタイプミスですか?そして、代わりに二重引用符を一重引用符の中にエスケープする必要があるのはなぜですか?多分文章を混ぜたと思う?
バイトコマンダー

@ByteCommanderはい、二重引用符で囲まれた二重引用符の概念は非常に一般的に使用されています- 顕著な実用例については、この投稿を参照してください。多くの場合、パス文字列に関して、スペースを含む文字列を保護するために行われます。二重引用符は、エスケープの有無にかかわらず単一引用符内で使用できますが、文字どおりに解釈されます。つまり、評価につながりません。この点はポストで明らかにします。
AsymLabs
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.