从我对 O'Reilly 的“Classic Shell Scripting”的阅读来看,您似乎希望在每个 shell 脚本的开头将输入字段分隔符 IFS 重置为换行符、空格和制表符,以防止潜在的恶意或其他格式错误的输入。
这实际上是每个 shell 脚本的最佳实践吗?对我来说,将其包含在每个 shell 脚本中似乎并不实际。
IFS='
'
答案1
如今,它绝对不是最佳实践所必需的,它只是混乱。从历史上看,这是值得商榷的。
历史沿革
从历史上看,sh 的某些实现IFS
像任何其他变量一样从环境继承,而其他实现则强制将其设置为其默认值(空格-制表符-换行符)。大多数 21 世纪的炮弹都是后者。
POSIX用于允许这两种行为:
实现可能会忽略调用 shell 时环境中的 IFS 值,将 IFS 视为未设置。
“将 IFS 视为未设置”实际上并没有描述典型行为,即将其设置为对字段分割具有与未设置相同效果的值。这在中讨论过奥斯汀集团增强请求 096它修改了措辞,但仍然允许保留或覆盖IFS
.
几年前这种情况发生了变化,之后奥斯汀集团缺陷 0000884“要求 sh 在启动时将 IFS 设置为<space><tab><newline>
”。该提案于 2015 年提交,并在 2016 年版中获得通过。POSIX:2008现在声明:
shell
<space> <tab> <newline>
在调用时应将 IFS 设置为。
其基本原理正是为了避免当脚本未IFS
在可能是从不受信任的来源设置的环境中设置和运行时通常出现的不良行为。
因此,如今,IFS
仅当您使用较旧的 shell 时才需要显式设置默认值,这些 shell 可能需要与标准实践有其他偏差。
这是最佳实践吗?
如果您的脚本从不受信任的来源继承环境变量,则可能会出现很多问题。IFS
这只是众多潜在问题中的一个。还有PATH
、、、、、、、 ……你有信心全部设置吗LD_LIBRARY_PATH
?你是否记得???PYTHONPATH
PERLLIB
PERL5LIB
RUBYPATH
LD_PRELOAD
TEXINPUTS
RSYNC_RSH
某些变量的名称包含()
?
如果您的脚本继承了具有任意名称的环境变量,那是你的问题,你无法从脚本内部修复它。不要运行能让对手无限制地决定环境中变量名称的 shell 脚本。这就是为什么须藤只允许白名单环境变量名称。
从历史上看,这主要是一个问题计算机图形图像处理不过滤环境变量名称的接口。这是利用的载体之一炮弹休克。良好的现代类似 CGI 的系统为所有变量添加前缀,并且只允许变量名称由 ASCII 字母数字和下划线组成。