Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Bash解析器以什么顺序在命令行中转义字符和拆分单词/标记?_Bash_Parsing - Fatal编程技术网

Bash解析器以什么顺序在命令行中转义字符和拆分单词/标记?

Bash解析器以什么顺序在命令行中转义字符和拆分单词/标记?,bash,parsing,Bash,Parsing,我试图明确地理解Bash解析器的业务顺序 wiki页面要求以下顺序: 读一行。 处理/删除引号。 以分号分隔。 处理“特殊操作员”,根据本条规定: 命令分组和大括号扩展,例如{…}。 过程替换,例如cmd1Posix为外壳解释提供了一种新的方法。但是,大多数shell(包括bash)都添加了自己的语法扩展。此外,该标准并没有坚持要求实际使用其算法;只是最终结果是一样的。因此,标准算法和关于单个外壳的描述之间存在一些差异。尽管如此,大致轮廓是相同的 理解标记化和分词之间的区别很重要。标记化将输入划

我试图明确地理解Bash解析器的业务顺序

wiki页面要求以下顺序:

读一行。 处理/删除引号。 以分号分隔。 处理“特殊操作员”,根据本条规定: 命令分组和大括号扩展,例如{…}。 过程替换,例如cmd1Posix为外壳解释提供了一种新的方法。但是,大多数shell(包括bash)都添加了自己的语法扩展。此外,该标准并没有坚持要求实际使用其算法;只是最终结果是一样的。因此,标准算法和关于单个外壳的描述之间存在一些差异。尽管如此,大致轮廓是相同的

理解标记化和分词之间的区别很重要。标记化将输入划分为具有语法意义的标记,然后shell语法使用这些标记对输入进行语法分析。在标准术语中,语法标记包括分号和括号运算符等。一种特殊类型的标记是单词

如标准所述,标记化基本上是解析输入的第一步,但如下文所述,它取决于引用字符的标识

随后可通过应用各种展开式来解释词语。应用于每个单词的精确扩展集取决于语法上下文;并不是所有的词都被一视同仁。这在标准的叙述性文本中有记录。应用于某些单词的一种转换是单词拆分,它根据字段分隔符的存在将一个单词拆分为一个单词列表,默认情况下为空白,并可通过更改IFS shell变量的值进行配置。分词不改变句法标记类型;事实上,当它发生时,句法分析已经完成

并不是所有的单词都要进行分词。特别是,除非进行了一些扩展,并且仅当扩展不在双引号内时,才会执行分词。即使如此,也不是在所有的句法语境中

将输入划分为令牌的算法必须与中的算法等效。该算法要求知道引用了哪些字符;大多数历史实现都是通过在内部用引号位标记每个输入字符来实现的。标记化过程中是否删除引用字符在某种程度上取决于实现;该标准将quote Removing步骤放在末尾,但如果最终结果相同,则实现可以更早地执行该步骤

请注意,=不是运算符字符,因此它不会导致var=foo拆分为多个标记。但是,shell解析器特别处理以标识符后跟=开头的令牌;它们后来被视为参数指定。但是,如上所述,分词并不会改变单词的句法性质,因此,由分词产生的单词(碰巧看起来像参数赋值)不会被shell解析器视为参数赋值。

Posix为shell解释提供了一个框架。但是,大多数shell(包括bash)都添加了自己的语法扩展。此外,该标准并没有坚持要求实际使用其算法;只是最终结果是一样的。因此,标准算法和关于单个壳的描述之间存在一些差异。尽管如此,大致轮廓是相同的

理解标记化和分词之间的区别很重要。标记化将输入划分为具有语法意义的标记,然后shell语法使用这些标记对输入进行语法分析。在标准术语中,语法标记包括分号和括号运算符等。一种特殊类型的标记是单词

如标准所述,标记化基本上是解析输入的第一步,但如下文所述,它取决于引用字符的标识

随后可通过应用各种展开式来解释词语。应用于每个单词的精确扩展集取决于语法上下文;并不是所有的词都被一视同仁。这在标准的叙述性文本中有记录。应用于某些单词的一种转换是单词拆分,它根据字段分隔符的存在将一个单词拆分为一个单词列表,默认情况下为空白,并可通过更改IFS shell变量的值进行配置。分词不改变句法标记类型;事实上,当它发生时,句法分析已经完成

并不是所有的单词都要进行分词。特别是,除非进行了一些扩展,并且仅当扩展未处于运行状态时,才会执行分词 旁边的双引号。即使如此,也不是在所有的句法语境中

将输入划分为令牌的算法必须与中的算法等效。该算法要求知道引用了哪些字符;大多数历史实现都是通过在内部用引号位标记每个输入字符来实现的。标记化过程中是否删除引用字符在某种程度上取决于实现;该标准将quote Removing步骤放在末尾,但如果最终结果相同,则实现可以更早地执行该步骤

请注意,=不是运算符字符,因此它不会导致var=foo拆分为多个标记。但是,shell解析器特别处理以标识符后跟=开头的令牌;它们后来被视为参数指定。但是,如上所述,分词并不会改变一个词的句法性质,因此,shell解析器不会将单词拆分产生的单词视为参数赋值。

shell解析的第一步是应用shell语法规则,这些规则必须提供中指定语法的超集

只有在这个初始阶段才能检测到任务,而且只有在非常特定的情况下:

语法分析器必须生成赋值\u单词标记注意语法分析器只运行一次,并且在任何扩展发生后都不会重新运行! =字符本身及其前面的有效变量名不能被引用。 如果没有显式调用eval,或者没有将结果作为代码传递给另一个shell,或者没有采取类似的显式操作,解析器永远不会在扩展结果上重新运行,因此,如果操作在进行扩展之前没有作为赋值进行解析,那么扩展的结果将永远不会生成赋值。

shell解析的第一步是应用shell语法规则,这些规则必须提供中指定语法的超集

只有在这个初始阶段才能检测到任务,而且只有在非常特定的情况下:

语法分析器必须生成赋值\u单词标记注意语法分析器只运行一次,并且在任何扩展发生后都不会重新运行! =字符本身及其前面的有效变量名不能被引用。
如果没有显式调用eval,或者没有将结果作为代码传递给另一个shell,或者没有采取类似的显式操作,那么解析器永远不会在扩展结果上重新运行,因此,如果操作在扩展发生之前没有作为赋值进行解析,那么扩展的结果将永远不会生成赋值。

我同意,我的问题要求很多,我非常感谢所有有价值的意见。我感谢@rici和@CharlesDuffy

下面是Bash如何解释和执行代码的概要

第1阶段:线路馈电 Shell按行读取输入

阶段2:标记化 行被切分为标记-单词和运算符,由元字符分隔。引用\、“…”、…得到尊重,替换别名,删除注释。令牌边界在内部记录

元字符有:,,|,&

第3阶段:命令解析 分析管线、列表和复合命令循环、条件、分组的行。这使Bash了解了执行子命令的顺序。然后,每个子命令通过其自己的解析周期分别进行处理

第四阶段:语法 命令名和重定向左侧的分配将被删除并保存以备以后使用

第五阶段:扩张 按以下顺序执行展开:

大括号扩展,例如{1..3}。 波浪形扩展,例如~root。 参数和变量展开,例如${var*/}。 算术扩展,例如$1+12。 命令替换,例如$date。
流程替代,如cat我同意,我的问题要求很多,我非常感谢所有有价值的输入。我感谢@rici和@CharlesDuffy

下面是Bash如何解释和执行代码的概要

第1阶段:线路馈电 Shell按行读取输入

阶段2:标记化 行被切分为标记-单词和运算符,由元字符分隔。引用\、“…”、…得到尊重,替换别名,删除注释。令牌边界在内部记录

元字符有:,,|,&

第3阶段:命令解析 分析管线、列表和复合命令循环、条件、分组的行。这使Bash了解了执行子命令的顺序。然后,每个子命令通过其自己的解析周期分别进行处理

第四阶段:语法 命令名和重定向左侧的分配将被删除并保存以备以后使用

第五阶段:扩张 按以下顺序执行展开: 大括号扩展,例如{1..3}。 波浪形扩展,例如~root。 参数和变量展开,例如${var*/}。 算术扩展,例如$1+12。 命令替换,例如$date。
进程替换,在支持的情况下,例如cat,一篇文章有很多问题。您是否尝试过阅读?在shell脚本中,单词拆分是一个非常特殊的术语,它只发生一次。它通常不指拆分字符串。根据shell语法解析字符串不被视为分词,类似awk{print$2}的命令也不被视为分词。@CharlesDuffy被编辑成单个问题。你会说它足够具体吗?@cblew:我编辑了我的答案,试图符合你的新问题。总的来说,最好是提出新的问题,而不是通过更改他们应该回答的问题来使已经提供的答案无效。一篇帖子有很多问题。你有没有试过阅读?分词在shell脚本中是一个非常特殊的术语,而且只发生一次。它通常不指拆分字符串。根据shell语法解析字符串不被视为分词,类似awk{print$2}的命令也不被视为分词。@CharlesDuffy被编辑成单个问题。你会说它足够具体吗?@cblew:我编辑了我的答案,试图符合你的新问题。总的来说,最好是提出新的问题,而不是通过改变他们应该回答的问题来否定已经提供的答案。总的来说,我认为最好是让人们看看Posix标准,虽然它需要作为一个整体来阅读,但它是准确且相当清晰的。在互联网上找到的摘要,包括你最初引用的一些摘要,可能是善意的,但它们往往会遗漏细节或无法将整个过程置于上下文中。例如,分词不适用于重定向或变量分配。此外,分词适用于未引用扩展的结果,而不是未引用的结果。有用的是一些具体的问题,比如为什么会出现这样的结果,而不是我预期的结果?这类问题侧重于实践中遇到的实际问题,如果措辞得当,可以产生更好的搜索结果。这基本上就是SO格式和问题指导原则的理由。总的来说,我认为最好让人们看看Posix标准,虽然它需要作为一个整体来阅读,但它是精确和合理清晰的。在互联网上找到的摘要,包括你最初引用的一些摘要,可能是善意的,但它们往往会遗漏细节或无法将整个过程置于上下文中。例如,分词不适用于重定向或变量分配。此外,分词适用于未引用扩展的结果,而不是未引用的结果。有用的是一些具体的问题,比如为什么会出现这样的结果,而不是我预期的结果?这类问题侧重于实践中遇到的实际问题,如果措辞得当,可以产生更好的搜索结果。这就是SO的格式和问题指导原则的基本理由。