![未加引号的元字符如何成为标记的一部分?](https://linux22.com/image/85865/%E6%9C%AA%E5%8A%A0%E5%BC%95%E5%8F%B7%E7%9A%84%E5%85%83%E5%AD%97%E7%AC%A6%E5%A6%82%E4%BD%95%E6%88%90%E4%B8%BA%E6%A0%87%E8%AE%B0%E7%9A%84%E4%B8%80%E9%83%A8%E5%88%86%EF%BC%9F.png)
在阅读了@Tim 关于 shell 语法的一些问题后,我正在浏览bash
手册页,然后我提出了我自己的一个(简单的)问题。
以下是摘录man bash
(请自行查看LESS=+/^DEFINITIONS man bash
:
word A sequence of characters considered as a single unit by the
shell. Also known as a token.
...
metacharacter
A character that, when unquoted, separates words. One of the
following:
| & ; ( ) < > space tab
control operator
A token that performs a control function. It is one of the fol-
lowing symbols:
|| & && ; ;; ( ) | <newline>
但这是我没有得到的圆圈:
;
是一个“元字符”。- “元字符”在不加引号时分隔“单词”。
- “令牌”是我们可以用来表示“单词”的另一个术语。
;;
是一个令牌。- 因此
;;
是一个词。
但是,这意味着它是一个由两个单词分隔符组成的单词。鉴于它没有被引用,并且不需要它周围的空白来识别(或者是吗??),这怎么可能?
如果您好奇,我正在阅读的有关 shell 语法的其他问题如下:
答案1
Bash 使用与 POSIX 相同的术语(毫不奇怪)。使用它进行比较(偶尔进行澄清)。
引用自定义
3.113 控制操作员
在 shell 命令语言中,执行控制功能的标记。它是以下符号之一:
& && ( ) ; ;; newline | ||
shell 内部使用的输入结束指示器也被视为控制运算符。
注:Token Recognition在XCU中有详细定义令牌识别。
3.407 代币
在 shell 命令语言中,shell 认为的字符序列单个单元读取输入时。标记可以是运算符或单词。
注:读取输入的规则在XCU中有详细定义令牌识别。
3.440 单词
在 shell 命令语言中,除运算符之外的标记。在某些情况下,单词也是单词标记的一部分:在各种形式的参数扩展(例如 ${name-word})和变量赋值(例如 name=word)中,单词是所描述的标记的一部分通过言语。在单词扩展之后,单词的概念不再适用,仅保留字段。
所以你看,“单词”和“令牌”之间有区别,并且它们不是问题中暗示的同义词。而且,该标准并不认为两个分号是单独的字符,而是一个单个单元。
答案2
bash
解析词法分析器生成的标记。当bash
把行分成单词时,很可能是使用字符。当它解析命令语法时,它使用标记。在这种情况下,;;
不是两个“;”字符,更确切地说,它是由两个“;”组成的令牌。 (分号)字符。 bash 的词法分析器以允许将字符组识别为标记的方式读取传入的字符流。因此,代码实际上看不到分号,而是看到令牌代码。
请参阅flex
和bison
工具来了解这一点。我不相信 bash 使用这些,但它们是用于类似解析应用程序的工具,并且有关于解析通常如何完成的概述材料。
这GNU Bash 参考手册是一个值得阅读的好文档。写得很好,但比手册页更具解释性。
答案3
是的,;;
是一个词。但它不是两个元字符在一起。
这是案例陈述的结尾:
case a in
[a-z]) echo "yes" ;;
esac
或者单行:
case a in [a-z]) echo "yes" ;; esac
是的,它与“是”之间用一个空格隔开,所以它是一个单词。
但不一定是这样:
case a in [a-z]) echo "yes";; esac
是的,非常具体的问题的措辞有时可能会令人困惑。