grep apple 文件和 grep "apple" 文件有什么区别?

Joh*_*cen 23 bash grep sh

grep apple file和 和有grep "apple" file什么区别?加引号有什么作用?它们似乎都在工作并做完全相同的事情(显示相同的行)。

Dav*_*ter 45

引号会影响 shell 认为特殊的字符并具有句法含义。在您的示例中,这没有区别,因为不apple包含此类字符。

但考虑另一个例子:grep apple tree fileapple在文件tree和中搜索单词file,而grep "apple tree" fileapple tree在文件中搜索单词file。引号告诉 bash,单词 space in"apple tree"不是新参数的开始,而是当前参数的一部分。grep apple\ tree file会产生相同的结果,因为\告诉 bash 忽略以下字符的特殊含义并按字面​​意思对待它。

  • 另一个重要的点是双引号(`"`)和单引号(`'`)之间的区别。单引号防止解释某些字符,例如`$`,而双引号允许解释。例如`grep '${USER} '` 将查找文本`${USER}`,而`grep "${USER}"` 将查找变量`USER` 包含的文本(例如`johnstacen`)。 (4认同)
  • 这也可以通过通配符看到。如果你执行 `grep a*b equations.txt` 那么它会搜索 `a*b`,除非当前目录中有一个文件以 a 开头,b 结尾,在这种情况下(因为 (ba)sh将在命令行上扩展文件名)grep 将使用完全不同的参数调用,从而导致不同的结果。这通常更像是 find 的问题,作为像 `find 这样的命令。-name *.txt` 将导致意外行为,如果当前目录中有 txt 文件。在这种情况下最好使用引号。 (2认同)

Asy*_*abs 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
Run Code Online (Sandbox Code Playgroud)

理解引号的工作方式对于理解 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)
Run Code Online (Sandbox Code Playgroud)

您可以使用单引号通过变量传递命令。单引号将阻止评估。双引号将评估。

# 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)
Run Code Online (Sandbox Code Playgroud)

您可以在双引号内使用单引号,也可以在双引号内使用双引号,但不应执行单引号内的双引号(不转义它们)将不会被评估,它们将按字面解释。单引号内的单引号不应该被执行(不转义它们)。

您需要彻底了解引号才能有效地使用 Bash。很重要!

作为一般规则,如果我希望 Bash 将某些内容扩展为元素(如数组),我不使用引号,我将单引号用于不会被更改的文字字符串,并且我对变量使用双引号可能返回任何类型的字符串。这是为了确保保留空格和特殊字符。