gpt4 book ai didi

linux - 历史扩展中的单引号(bash)

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:17:38 24 4
gpt4 key购买 nike

我有一个关于bash语法的理论问题。
我在linux ubuntu 14.04中运行bash 4.3.11(1)。
在GNU官方网站:Bash official web (GNU)
在第9.3.1子节中。上面写着:
啊!一串
参考当前位置之前的最新命令
在以字符串开头的历史记录列表中。
一般来说,string是一个字符序列,在句法上,在第一个空白或换行之前结束。
然而,当在第3.1.2小节中描述引用时,我们可以在第3.1.2.2段中阅读。以下内容:
将字符括在单引号('')中可以保留文本
引号中每个字符的值。
特别是,单引号中的空格不在分隔词中串字符串。
因此,像!'some text'这样的表达式必须在bash的历史列表中搜索以'some text'开头的最新命令。
但是,当我在我的终端上写时,sometext之间的空白被打破了,因为下面的错误信息被显示出来:
猛击:!'某些:未找到事件
这种行为是shell实现中的一个bug,还是我不理解这个例子中bash的扩展规则?

最佳答案

我不会将观察到的行为称为bug,因为除了bash shell本身的观察到的行为之外,没有其他关于历史扩展的规范。但确实是这样,解析历史扩展表达式的精确机制没有很好的文档记录,并且有很多可能令人惊讶的角落案例。
bash手册页确实声明,历史扩展“在shell将其分解成单词之前,在读取完整行之后立即执行”(强调部分已添加),而bash手册提到历史扩展是由历史库提供的。这是大多数历史扩展解析异常的根本原因:历史扩展在没有任何bash标记器帮助的情况下对原始的未分析输入进行工作,并且主要是使用一个不是bash特定的外部库来完成的。由于输入是不平凡的,所以在历史扩展中使用的相对简单的解析规则只不过是对真实分析的粗略近似,这并不奇怪。
例如,bash手册确实指出可以防止历史扩展字符(!)通过引用反斜杠来识别它。但是没有明确的文件证明任何紧跟在!将禁止识别历史扩展,即使反斜杠本身是用反斜杠引用的。所以!inbash不会导致以\\!word开头的前一个命令被替换。(word是执行命令\\word而不是别名word的常用方法,因此示例并不完全是人为的。)
this answer中可以找到一些有关识别历史扩展字符的角点案例的详细讨论。
这个问题提出的问题略有不同,因为它是关于历史扩展解析的下一个阶段。一旦确定某个特定字符是历史扩展字符,就需要解析下面的“事件”;如bash手册所示,该事件可以采用多种形式,其中一种是word,表示以“!string开头的最新命令。
这意味着,只有在没有其他表单应用时才会使用此表单,这意味着string不能以数字或-,!或者?。它也不能以空白或=(因为它们会抑制历史扩展)开头,在某些情况下(或)(可能会抑制历史扩展)。最后,它不能以^、$、%或*开头,这将被解释为单词指示符(来自默认事件,这是前一个命令)。
bash manual没有指定终止string的内容。它在string library manual中有半个文档,其中提到历史搜索字符串(或bash手册中所称的“event”)由空白、:,或历史配置变量history中的任何字符终止。(对于记录,history_search_delimiter_chars当前(v4.3)将该变量设置为bash
如前所述,在决定是否识别历史扩展字符时要考虑引号;事实证明,如果历史扩展发生在双引号字符串中,则结束双引号也被视为历史搜索分隔符字符。据我所知,这是整个字符列表,它将限定";&()|<>"
在bash或历史文档中,没有任何地方声明可以通过引用使历史搜索分隔符变为非特殊字符,而且事实上这不会发生。一个开放的引号,无论是双引号还是单引号,甚至是后面的反斜杠!将被视为要搜索的!string的一部分,无需任何特殊处理。
子字符串匹配历史扩展--string的解析完全不同。该字符串只能由一个?或者换行。(正如bash手册所说,拖尾?如果以换行符结尾,则为可选。)
一旦识别出历史扩展字符并识别出历史搜索字符串,就可能需要将检索到的历史条目拆分为单词。同样,bash手册对于角点的情况略显傲慢,因为它说“行被分解成单词的方式与bash相同,因此被引号包围的几个单词被认为是一个单词。”
一个学究会注意到,“以bash做的同样的方式”与“bash做的完全一样”并不完全相同,事实上,句子的第二部分是literall true:即使引号不是真正匹配的引号,被引号包围的几个单词也被认为是一个单词。例如,行:

command "$(echo " foo bar ")"

历史图书馆认为由以下五个词组成:
0. command
1. "$(echo "
2. foo
3. bar
4. ")"

尽管bash解析会有很大的不同。相比之下,bash和history库同意解析
command "$(echo ' foo bar ')"

两个字。

关于linux - 历史扩展中的单引号(bash),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27735711/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com