checkbashisms:“类型”有什么问题?

checkbashisms:“类型”有什么问题?
#!/bin/sh

foo() {
   echo "in foo"
}

type foo

checkbashisms.pl明明不喜欢type,为什么呢?

$ checkbashisms.pl foo.sh
possible bashism in foo.sh line 7(type):
type foo

不是POSIX吗?但所有常见的 shell 都支持它(即bash, zsh, dash, busybox sh, mksh; 甚至在ksh; 中也许只是csh不支持它),难道没有办法抑制这个警告吗?

答案1

typePOSIX 的一部分,但作为 X/开放系统接口选项 (XSI) 的一部分。手册checkbashisms明确地说

请注意,在此上下文中 bashism 的定义大致相当于“不需要 POSIX 支持的 shell 功能”;这意味着 POSIX 的可选部分(例如 XSI 或用户可移植性)可能允许标记的某些问题。

之所以type被标记,是因为它是一个可选功能。

checkbashisms除了从脚本中删除它们之外,我不知道有任何方法可以禁用 中的特定警告。

答案2

考虑command -v foocommand -V foo代替type foo。有人告诉我它更可靠并且更有可能是内置的。

让我们在$PATH可执行文件、内置函数、函数和别名上测试一下:

#!/bin/sh

foo() {
   echo "in foo"
}
alias bar=foo

for cmd in sed command foo bar; do
  type "$cmd"
  command -V "$cmd"
  command -v "$cmd"
done

输出(使用短跑0.5.11):

sed is /usr/bin/sed
sed is a tracked alias for /usr/bin/sed
/usr/bin/sed
command is a shell builtin
command is a shell builtin
command
foo is a shell function
foo is a shell function
foo
bar is an alias for foo
bar is an alias for foo
alias bar='foo'

(笔记:sed不是别名!也许这指的是破折号散列命令位置表?)

尝试在 bash 中运行它,您会收到错误typecommand -V因为 bash 不会在非交互式脚本中启用别名。 Bash 还将在给定的多行上显示整个函数定义command -V,这确实很难解析。

POSIX定义command的选项作为:

-p使用 PATH 的默认值执行命令搜索,保证找到所有标准实用程序。

-v将字符串写入标准输出,指示当前 shell 执行环境中 shell 将使用的路径名或命令(请参阅Shell执行环境),调用 command_name,但不调用 command_name。

  • 实用程序、常规内置实用程序、包含字符的 command_names 以及使用 PATH 变量找到的任何实现定义的函数(如命令搜索和执行),应写为绝对路径名。
  • shell 函数、特殊内置实用程序、与 PATH 搜索无关的常规内置实用程序以及 shell 保留字应仅写为它们的名称。
  • 别名应写为代表其别名定义的命令行。
  • 否则,不应写入任何输出,并且退出状态应反映未找到该名称。

-V将一个字符串写入标准输出,指示 shell 在当前 shell 执行环境中如何解释 command_name 操作数中给定的名称(请参阅Shell执行环境),但不调用 command_name。尽管该字符串的格式未指定,但它应指示 command_name 属于以下哪一类别,并应包含所述信息:

  • 实用程序、常规内置实用程序以及使用 PATH 变量找到的任何实现定义的函数(如命令搜索和执行),应如此标识并在字符串中包含绝对路径名。
  • 其他 shell 函数应标识为函数。
  • 别名应被标识为别名,并且它们的定义包含在字符串中。
  • 特殊内置实用程序应标识为特殊内置实用程序。
  • 与 PATH 搜索无关的常规内置实用程序应被标识为常规内置实用程序。 (不需要使用术语“常规”。)
  • Shell 保留字应标识为保留字。

在编写 shell 脚本时,我强烈建议使用command -v而不是typeor,command -V因为它是三个中唯一具有定义输出的之一。话又说回来,我的大多数脚本都是通过一个静默的辅助函数来调用它的,该函数在确定我们是否有命令时完全忽略它的输出:

we_have() { command -v "$1" >/dev/null 2>&1; }

if we_have obscure-command; then
  osbcure-command …
fi

答案3

该命令type绝对不是 a bashism,因为它是自 1984 年以来的一部分UNIX

然而,如果您使用的是仅提供基本兼容性的小型嵌入式平台,则该type命令可能不存在。POSIX

如果您所在的平台自称为UNIX-platform,则该type命令是强制性的,因为UNIX需要 -platform 来支持全部XSI标准中提到的所谓增强功能POSIX

如果您正在寻找即使小型嵌入式系统也需要支持的半相似命令,您可能会喜欢使用:

command -V foo

反而。请注意,大写的 -V 选项command打印与 类似但不一定相同的输出type

另请注意:标准未定义fromcommand -V或 from 的输出格式。typePOSIX

相关内容