可执行文件名称中带有“#”的危险?

可执行文件名称中带有“#”的危险?

这可能是一个常见问题解答——如果这是一个骗局,很高兴能解决这个问题——但我不知道如果是这样的话如何找到它。我也很高兴得到一个简单地告诉我如何找到语法相关文档的答案。 (man bash是老朋友了。)

我想将 shell 脚本命名为“f#”:

#!/bin/sh
dotnet fsi "$@"

这将作为从 bash 命令行运行的快捷方式,以便启动 F# 编程语言的可执行文件。

令我惊讶的是,尽管“#”是 shell 注释字符,但它仍然有效。我什至可以将参数传递给脚本:

$ f# hello.fsx
Hello World from F`
$

我可以将前面的命令嵌入到脚本中并毫无问题地运行该脚本。 (!)

似乎规则是“#”仅在前面有空格或位于行首时才引入注释。否则它会被视为 bash 中的普通字符。那是对的吗?

如果我使用“f#”作为脚本名称,是否有一些不明显的问题可能会在以后困扰我?

答案1

在所有类似 sh 的 shell 中,包括所有版本的 bash 和 zsh,#仅启动评论当它位于单词的开头时。这意味着它必须位于脚本或嵌套 shell 的开头(例如$(# this is a comment,结束符)需要位于单独的行上),前面有一个空白字符,或者前面有一个运算符字符(其中之一&|;<>)。后面f#永远不会f有注释开始。

有些地方#有特殊含义,但在 bash 中,我想不出当它是不是第一个字符的单词的一部分时它会出现什么情况,并且 bash 需要一个单词。 (当 bash 期望不同的东西时,它当然有特殊的含义;例如,你绝对不能将其#作为变量名的一部分。)在 zsh 中,#通配符extended_glob如果设置了(经常启用)选项。#别名不会有问题(别名在通配之前扩展),但脚本名称会出现问题。

请注意,这仅涉及外壳。其他工具可能有问题#:它作为配置文件中的注释字符很常见。例如,我不确定您是否可以#在 Git 别名的扩展中包含 a 。

答案2

2022 年 9 月 GNU Bash 5.2 版参考手册表示“以 # 开头的单词会导致该单词和该行上的所有剩余字符被忽略”。单词是“被 shell 视为一个单元的字符序列。单词可能不包括未加引号的元字符”。 “#”字符不是元字符的一部分。

bash 2.05 的文档并不那么精确,但根据我对 bash 1.14.7 之前的几个版本的 GNU 源代码的分析,“#”字符可以是单词的一部分,因此也是“f#”的一部分。

当前的许多“/bin/sh”路径实际上是 bash shell。所以那里没有太大的风险。

因此,陷阱不会来自 bash,但可能来自其他工具。例如,有一个无效的bash 的 BNF 语法这可能会误导其他解释 bash 脚本的工具的实现。

Bash V2 BNF 摘录:

<ALPHA> ::= a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
             A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z

<DIGIT> ::= 0|1|2|3|4|5|6|7|8|9

<NUMBER> ::= <DIGIT>
           | <NUMBER> <DIGIT>

<WORD> ::= <ALPHA>
         | <WORD> <ALPHA>
         | <WORD> '_'

问题主要是有一些程序将任何(不带引号的)“#”解释为注释的开头。最“烦人”的可能是代码样式格式化程序,例如美丽什它确实可以正确处理它,但其他人可能不会。

真正的问题是编辑器中的样式:vim 将单词内的“#”视为注释的开头,其他几个环境也是如此。因此,您最终会为“f#”解释器的参数提供错误的颜色代码。这些语法荧光笔是错误的,单独修复它们应该不会太难,但其中有相当多... vim 8.2 的某些版本会按应有的方式对代码进行颜色显示,其他 vim 8.2 版本不会 - 区别可能是在 vim 8.2 补丁之一中。

只要“f#”供个人使用,或者在您可以控制的系统上,您应该是安全的 - 对于全球(全球)使用,我会更加小心 - 我不赞成看到它在 debian 中分发实例。

相关内容