bash中`和'有什么区别?

Rya*_*uza 3 macos bash terminal

在OS X终端中运行此语句

for i in `ls -v *.mkv`; do echo $i; done
Run Code Online (Sandbox Code Playgroud)

将按名称顺序成功打印出目录中的所有文件名,每个文件名都在其自己的行上.

来源:这个StackOverFlow答案

但是,如果我在OS X终端中运行此语句

for i in 'ls -v *.mkv'; do echo $i; done
Run Code Online (Sandbox Code Playgroud)

输出是"ls -v fileName1.mkv fileName2.mkv"等,所有文件名连接成一个长行(而不是每个都在自己的行上打印).

我的问题是:

  1. bash中`和'有什么区别?
  2. 为什么这种差异对完全不同的输出负责?
  3. 什么键盘组合产生`?(键盘组合)

hig*_*aro 7

1)执行反引号之间的文本并替换为所附命令的输出,因此:

echo `echo 42`
Run Code Online (Sandbox Code Playgroud)

将扩展为:

echo 42
Run Code Online (Sandbox Code Playgroud)

这称为命令替换,也可以使用语法实现$(command).在您的情况下,以下内容:

for i in `ls -v *.mkv`; do ...
Run Code Online (Sandbox Code Playgroud)

被替换为类似的东西(如果您的目录包含3个名为a.mkv,b.mkvc.mkv的文件):

for i in a.mkv  b.mkv  c.mkv; do ...
Run Code Online (Sandbox Code Playgroud)

引号双引号之间的文本只是普通的Bash字符串,其中包含像spacescaped 一样的字符(在Bash中引用字符串的其他方法在此处描述):

echo "This is just a plain and simple String" 
echo 'and this is another string' 
Run Code Online (Sandbox Code Playgroud)

使用'和之间的区别"插入的字符串"可以插入变量,例如:

variable=42
echo "Your value is $variable"
Run Code Online (Sandbox Code Playgroud)

要么:

variable=42
echo "Your value is ${variable}"
Run Code Online (Sandbox Code Playgroud)

打印:

Your value is 42
Run Code Online (Sandbox Code Playgroud)

2)通配符表达式*.mkv在称为Globbing的过程中被扩展的文件名替换.在大多数命令中使用通配符激活Globbing,而不将表达式括在字符串中:

echo *.mkv
Run Code Online (Sandbox Code Playgroud)

将打印:

a.mkv b.mkv c.mkv
Run Code Online (Sandbox Code Playgroud)

与此同时:

echo "*.mkv"
Run Code Online (Sandbox Code Playgroud)

打印:

*.mkv
Run Code Online (Sandbox Code Playgroud)

循环中的i变量for取值" ls -v *.mkv"但echo循环体内的命令$i不带引号,因此Bash在那里应用了globbing,最后得到以下结果:

for i in 'ls -v *.mkv'; do 
   #   echo $i 
   #
   # which is expanded to:
   #   echo ls -v *.mkv    (no quotes) 
   #
   # and the globbing process transform the above into:
   echo ls -v a.mkv b.mkv c.mkv
Run Code Online (Sandbox Code Playgroud)

在应用globbing之后,这只是一个带有文件名的单行字符串.


3)这取决于您的键盘布局.

保持角色的一个技巧是使用程序ascii,搜索角色96(十六进制60),复制它并将其保存在剪贴板上(您可以使用parcellite或任何其他适合您需要的剪贴板管理器).


更新:正如@triplee建议的那样,你应该检查无用的使用,ls因为这被认为是一个重击陷阱,并且有更好的方法来实现你想要做的事情.