解开 echo 'a'* 中的路径名扩展和引号删除

解开 echo 'a'* 中的路径名扩展和引号删除

Shell 是:GNU bash,版本 5.1.16(1)-release (x86_64-pc-linux-gnu)

当前工作目录下有两个文件:

  • 一个名为abc.txt
  • 'a'bc.txt一个名为(使用创建touch \'a\'bc.txt)的文件

我运行以下命令:

echo 'a'*

输出是:

abc.txt

GNU bash 手册指定在路径名扩展之后处理引号删除。

因此,我期望这个命令匹配'a'bc.txt但不匹配abc.txt。 !

我预计上述命令将按如下方式进行:

  • 在路径名扩展阶段,尝试匹配任何文件名以'a''a'作为文字字符串)开头的文件,并因此匹配'a'bc.txt
  • '在引号删除阶段,删除in 中的单引号,'a' 而不影响上一步中发生的路径名扩展的结果。

显然这里有一些我不明白的地方。

我找不到这个具体问题的任何文档或答案。

答案1

您描述它的方式将使得无法匹配以 *.目前的工作方式是,可以编写'*'*,其中第一个星号被引用,因此是一个文字,而第二个星号保留匹配任何内容的特殊含义。如果引号(以及对称的反斜杠)本身需要在文件名中找到匹配的字符,那么这是不可能的。


我不确定 shell 的内部实现是如何工作的,或者短语“引用删除”背后的历史是什么,但我发现最好考虑被引用字符的(隐藏)属性的状态,而不是认为在最初处理命令行之后,引号字符实际上作为单独的实体存在。

因此,当您编写 时'*'*,您会得到**,其中(希望至少几乎看不见)粗体将字符标记为被引用。然后,如果您想匹配文字引号,则需要引用或转义它。例如,"'*'"*将给出'*'*,即引用的引用-星号-引用,以及一个通常特殊的星号。 (我想我听说一些早期的 shell 实现使用字节的第 8 位来标记引用的字符,但当然这只适用于 7 位字符集。)

或者,如果您愿意,只需将引号视为特殊字符,仅用于确定另一个字符是否被引号引起来,而不是用于与目标字符串中的字符进行匹配。

相关内容