如何在 bash 中解释具有多种引号的字符串?

How are strings with multiple kinds of quotes interpreted in bash?

提问人:interesting 提问时间:5/14/2022 最后编辑:Charles Duffyinteresting 更新时间:5/14/2022 访问量:338

问:

为了提供上下文,我正在尝试创建一个简单的 bash 版本,为此,我需要模仿 bash 使用多组单引号和双引号解析内容的方式。我无法弄清楚 bash 处理引号内引号的整体过程。我注意到一些重复的模式,但仍然没有全貌。

例如,这个例子:

$ "'"ls"'"

评估结果为:

$ 'ls'

甚至是这个更丑陋的例子:

$ "'"'"""'"ls"'"""'"'"

评估结果为:

$ '"""ls"""'

我注意到出现了以下模式:

  • 如果换行引号的计数为偶数,则仅计算反引号内的内容
  • 如果换行引号的计数为奇数,则计算为反引号内的内容(包括)。

例如,甚至换行引号:

$ ""'ls'""

评估反引号(单引号)内的内容,而不使用单引号本身,评估:

$ ls

或者对于包装器报价的奇数计数:

$ '''"ls"'''

它计算双引号的内容(包括):

$ "ls" : command not found.

尽管如此,我还是无法全面了解引号内更复杂引号的这种解析模式是如何完成的。

bash shell 解析 报价

评论

2赞 William Pursell 5/14/2022
这并不是真正的“引号中的引号”。该字符串不包含任何嵌入的引号。相反,它是 3 个字符串的串联。空字符串(用 表示)后跟(给定为 )和空字符串。""'ls'""""ls'ls'
2赞 that other guy 5/14/2022
您是否知道 Bash 主要遵循 POSIX sh,这是一个有据可查的标准?
1赞 Charles Duffy 5/14/2022
正如另一个人所暗示的那样:尝试构建“一个简单的 bash 版本”首先是一个糟糕的起点:bash 在更简单(但不简单)的标准之上添加了额外的复杂性。从这个标准开始;如果您需要它未涵盖的任何内容,请在基础知识正常工作从那里构建。
1赞 Charles Duffy 5/14/2022
顺便说一句,这与你在这里的问题无关,但 bash 会跟踪每个字符的引用类型,因为下游处理可能会因每个字符的引用方式而异。你不想仅仅根据这个问题的答案来构建一个解析器,然后发现你没有跟踪每个字符的解析方式(并且你需要这些信息来正确实现某些行为)!
1赞 John Kugelman 5/14/2022
@CharlesDuffy 报价类型如何影响下游处理?我的心智模型一直是,bash 只是跟踪一个角色是否被引用。你是说单引号、双引号和反斜杠可以有不同的可观察行为?

答:

4赞 Barmar 5/14/2022 #1

报价按顺序处理,寻找匹配的收盘报价。起始引号和结束引号之间的所有内容都变成一个字符串。嵌套引号没有特殊含义。

"'"ls"'"

当它处理第一个 时,它会扫描以查找下一个字符串的结尾,其中包含 。""'

然后它扫描固定字符串。ls

当它处理 after 时,它会扫描寻找下一个 ,从而产生另一个字符串。"ls"'

这些都是串联的,导致 .'ls'

"'"'"""'"ls"'"""'"'"

"'"是字符串 。'

'"""'是字符串"""

"ls"是字符串ls

'"""'是字符串"""

"'"是字符串 。'

将它们连接在一起会产生'"""ls"""'

""'ls'""

""是一个空字符串。 是字符串 。 是另一个空字符串。将它们连接在一起会产生 .'ls'ls""ls

'''"ls"'''

''是一个空字符串。 是字符串(包含文本双引号)。 是一个空字符串。将它们连接起来会产生 .由于没有具有该名称的命令(包括文字双引号),因此会出现错误。'"ls"'"ls"''"ls"

单引号和双引号之间存在差异,但它们不会影响您发布的任何示例。请参阅 Bash 中单引号和双引号之间的区别