参数扩展中的嵌套双引号

Nested double quotes in parameter expansion

我很惊讶以下是有效的 Parameter Expansion。注意双引号内有未转义的双引号:

result="${var1#"$var2"}"

有人可以帮我解析一下吗?

大括号内有双引号,没问题。

但是在这种情况下需要 none 个。

result=${var1#$var2}

即使对于包含空格和换行符的值也同样有效。

答案是它们被分开解析。让我们简单了解一下字符串。

result="${var1#"$var2"}" 在这种情况下实际上不需要任何引号,但无论如何都要查看字符串...

result="...

解析器说 meh,这是一个任务,我 知道该怎么做,我会忽略这些,它们不会伤害任何东西,但现在我必须找到终止匹配项。 然后它逐字节读取引号后的值,寻找终止双引号。这将启动一个新的上下文 1。

result="${...

一旦它看到开卷曲,它就知道在看到匹配结束卷曲之前不会出现终止引号。它启动了一个新的 context-2。

result="${var1#"...

在这个子上下文中看到一个新的双引号使它成为内部 new context-3 的 opening 引号。

result="${var1#"$var2"...

当它看到这个双引号时,它会将它与前一个双引号匹配,关闭 context-3,回到 context-2。

result="${var1#"$var2"}...

这个 close-curly 允许它关闭仍然打开的 context-2,回到 context-1。

result="${var1#"$var2"}"

找到这个现在结束的双引号允许它关闭 context-1。下面的换行符可以作为整个术语的终止符,因此可以对其进行评估和赋值。

反斜杠引用内部双引号,例如,会将它们添加到用于尾部的字符串术语中 trim,这可能会因此而失败。

$: var1=aaa
$: var2=a
$: result="${var1#"$var2"}"
$: echo $result                # does what you want/expect
aa
$: result="${var1#\"$var2\"}"  # does NOT
$: echo $result
aaa

在不使用引号的情况下,解析器知道这是一个赋值,并且处理这些值的方式与评论中提到的略有不同,但通常会将它们视为被引用。

$: result=${var1#$var2}
$: echo $result
aa

这意味着它不必处理 context-1context-3,只需要担心卷曲关于。最终结果是一样的。

更好?