【问题标题】:Why do backslashes prevent alias expansion?为什么反斜杠会阻止别名扩展?
【发布时间】:2011-09-04 00:13:33
【问题描述】:

在我的问题的第一部分,我将提供一些背景信息作为 为社区服务。第二部分包含实际问题。

第一部分

假设我创建了以下别名:

alias ls='ls -r'

我知道如何在下面临时取消别名(即覆盖此别名) 方式,使用:

1) 命令的完整路径名:/bin/ls

2) 命令替换:$(which ls)

3) 内置命令:command ls

4) 双引号:"ls"

5) 单引号:'ls'

6) 反斜杠字符:\ls

案例 1 很明显,案例 2 只是一个变体。案例 3 中的内置命令旨在忽略 shell 函数,但显然它也适用于规避别名。最后,案例4和案例5都符合POSIX standard (2.3.1)

"一个被识别的结果词 成为 a 的命令名单词 简单的命令将被检查到 确定它是否是未引用的, 有效的别名。”

还有Bash Reference Manual (6.6):

"每个简单的第一个单词 命令,如果未引用,则检查为 看看有没有别名。”

第二部分

问题来了:为什么是案例 6(通过说 \ls 覆盖别名) 考虑引用这个词?按照这个问题的风格,我正在寻找对“官方”文档的参考。

文档说反斜杠只能转义以下内容 字符,而不是单引号和双引号,它引用一个 字符序列。 POSIX standard (2.2.1)

"未引用的反斜杠应 保留字面值 跟随字符,与 "

的例外

Bash Reference Manual (3.1.2.1)

"不带引号的反斜杠‘\’是 Bash 转义字符。它保存 下一个的字面值 随后的字符,与 换行符除外。”

(顺便说一句,“下一个角色”是不是有点矫枉过正?)

一个可能的答案可能是这种情况并不特别:它是 类似于 ANSI-C 引用中的一些情况,例如\nnn。然而,这仍然是 转义单个字符(值为八进制的八位字符 值 nnn),而不是字符序列。

【问题讨论】:

  • 请注意:第 6 个与前 5 个不同:前 5 个绕过函数和别名,而 \ls 将(在 bash 中)仅绕过别名,而不是同名函数.即:alias ls='echo "aliased"' ; function ls { echo "function" ; } ; ls ; \ls ; command ls:第一个(ls)将显示“aliased”,第二个(\ls)仅绕过别名,因此显示“function”,第三个(命令 ls)显示常规 ls 的输出
  • 这是一个很好的问题,但似乎没有任何解释能解决我对此事的任何困惑。 @alexandros-gezerlis,如果你能理解原因,你能帮我(家里的人)拼出来吗?
  • @OlivierDulac 5 至少在 GNU bash 4.3.11 中没有绕过功能

标签: bash shell escaping posix alias


【解决方案1】:

从历史上看,并由 POSIX 维护,引用单词的任何部分都会导致整个单词被认为是出于函数和别名扩展的目的而被引用。它也适用于引用此处文档的结束标记:

cat << \EOF
this $text is fully quoted
EOF

【讨论】:

  • 谢谢。我已经编辑了这个问题(第二部分的第一段),以澄清我错误地认为很明显的内容:我将不胜感激。
  • 另外,我刚刚注意到这里文档上的 POSIX 2.7.4 明确说明了转义的情况:“如果 word 中的任何字符被引用,则分隔符应通过对 word 执行引号删除来形成” .但是,在关于令牌识别的一般部分(POSIX 2.3)中明确指出,here-documents 是特殊的:“这些行应使用两种主要模式进行解析:普通令牌识别和处理 here-documents。”
  • @Alexandros:这些都有点模棱两可。您想进一步阅读第 2.7.4 节,在您的第一个引用之后:“如果 word 中没有引用任何字符,则应扩展 here-document 的所有行以进行参数扩展、命令替换和算术扩展。在在这种情况下,输入中的反斜杠表现为双引号内的反斜杠(请参阅双引号)。但是,不应在 here-document 中对双引号字符('"')进行特殊处理,除非双引号-quote 出现在 "$()"、"``" 或 "${}" 中。"
  • @geekosaur:对不起,但我不明白这有什么关系。我不明白您引用的句子(讨论没有引用 word 中的字符的情况)与您的示例相关,其中 word is 中的第一个字符被引用,这可能是原因为什么没有发生参数扩展。您的示例也适用于 E\OF。最后,我仍然不明白这一切是如何超出 here-documents 的,尤其是考虑到我的第二次引用。
  • 随机附注:显然(至少在我尝试过的 shell 中),在单词的某处有一对空引号被视为引用单词的一部分(例如:@ 987654322@、l""scat &lt;&lt;EOF'')。
【解决方案2】:

为了完成,这里还有另一种抑制别名和函数查找的方法(通过为单个命令清除整个 shell 环境):

# cf. http://bashcurescancer.com/temporarily-clearing-environment-variables.html
env -i ls

【讨论】:

    【解决方案3】:

    \ls 只引用第一个字符而不是整个单词。相当于写'l's。

    你可以这样验证:

    $ touch \?l
    $ \??
    bash: ?l: command not found
    

    如果\??引用了它会说的整个词?? not found 而不是 ?l not found。

    即它与以下效果相同:

    $ '?'?
    bash: ?l: command not found
    

    而不是:

    $ '??'
    bash: ??: command not found
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-12
      • 2021-11-16
      • 2019-01-28
      • 1970-01-01
      • 2011-01-23
      相关资源
      最近更新 更多