我将坚持使用脚本功能。丰富的交互功能(命令行版本,完成,提示等)往往会大相径庭,以完全不兼容的方式实现相似的效果。zsh中有哪些功能,bash中缺少哪些功能,反之亦然?给出了一些交互式使用的指示。
最接近bash的是ATT ksh93或mksh(Korn Shell和克隆)。Zsh也具有功能的子集,但是您需要以ksh仿真模式而不是zsh纯模式运行它。
我不会列出POSIX功能(可在任何现代sh
外壳程序中使用),相对晦涩的功能,也不会列出用于交互式使用的上述功能。从Debian wheezy上发现,bash 4.2,ksh 93u和mksh 40.9.20120630的观察结果有效。
$'…'
(带有反斜杠插值的文字字符串)在ksh93和mksh中可用。$“…”(翻译后的字符串)特定于bash。
Mksh和ksh93必须;&
在case
声明中使用,但不能;;&
测试后续案例。Mksh具有;|
此功能,最近的mksh允许;;&
兼容。
((…))
算术表达式和[[ … ]]
测试是ksh的功能。一些条件运算符有所不同,请参见下面的“条件表达式”。
Ksh和bash都有协同处理,但是它们的工作方式不同。
Mksh和ksh93除支持function name {…}
标准外name () {…}
,还支持函数定义的语法,但function
在ksh中使用时会更改作用域规则,因此name () …
要保持兼容性。函数名称中允许使用的字符的规则各不相同;坚持字母数字和_
。
Ksh93和mksh支持大括号扩展{foo,bar}
。{1..42}
Ksh93 支持数字范围,但mksh不支持。
ksh93的与mksh支持子提取${VAR:offset}
和${VAR:offset:length}
,但不区分折叠状${VAR^}
,${VAR,}
等等。你可以做大小写转换typeset -l
,并typeset -u
在两者的bash和ksh。
他们支持用${VAR/PATTERN/STRING}
或替换${VAR/PATTERN//STRING}
。STRING的引用规则略有不同,因此请在STRING中避免反斜杠(可能还有其他字符)(构建变量,${VAR/PATTERN/$REPLACEMENT}
如果替换包含引号字符,则使用反斜杠)。
阵列扩展(${ARRAY[KEY]}
,"${ARRAY[@]}"
,${#ARRAY[@]}
,${!ARRAY[@]}
在bash)工作像ksh的。
${!VAR}
扩展到is ${OTHERVAR}
的值(间接变量引用)特定于bash的情况(ksh与有所不同)。要在ksh中实现这种双重扩展,您需要使用名称引用()。工作原理相同。VAR
OTHERVAR
${!VAR}
typeset -n VAR=OTHERVAR; echo "$VAR"
${!PREFIX*}
进程替换<(…)
,>(…)
在ksh93中受支持,但在mksh中不受支持。
需要shopt -s extglob
在bash中激活的ksh扩展glob模式始终在ksh93和mksh中可用。
Mksh不支持字符类[[:alpha:]]
。
Bash和ksh93定义了伪文件和,但是mksh没有。/dev/tcp/HOST/PORT
/dev/udp/HOST/PORT
在脚本重定向扩大通配符(如var="*.txt"; echo hello >$a
写入a.txt
,如果该文件名是该模式的唯一的比赛)是一个bash特有的功能(其它炮弹从来没有做到这一点的脚本)。
<<<
这里的字符串在ksh中的作用就像在bash中一样。
>&
mksh也支持重定向语法错误的快捷方式,但ksh93不支持。
[[ … ]]
双括号语法
像bash一样,ATT ksh93和mksh都支持ksh的双括号语法。
文件运算符
Ksh93,mksh和bash支持POSIX的相同扩展名,包括,(粘性),(由egid拥有),(由euid拥有),(相同文件),(比新),(比旧)更旧的-a
同义词。-e
-k
-G
-O
-ef
-nt
-ot
-N FILE
(自上次读取以来已修改)不受mksh支持。
Mksh没有正则表达式匹配运算符=~
。Ksh93具有此运算符,并且其执行与bash中相同的匹配,但BASH_REMATCH
此后没有等效于检索匹配的组的操作。
字符串运算符
Ksh93和mksh支持相同的字符串比较运算符,<
并且>
作为bash以及的==
同义词=
。Mksh不使用语言环境设置来确定字典顺序,而是将字符串作为字节字符串进行比较。
其他运营商
-v VAR
测试是否定义了变量是bash特定的。在任何POSIX Shell中,您都可以使用[ -z "${VAR+1}" ]
。
别名中允许的字符集在所有shell中都不相同。我认为这与功能相同(请参见上文)。
Ksh93具有一个名为的内置builtin
函数,但它不会将名称作为内置命令来执行。使用command
旁路别名和功能; 如果存在,则会调用一个内置命令,否则将调用一个外部命令(可以使用来避免这种情况PATH= command error_out_if_this_is_not_a_builtin
)。
这是特定于bash的。你可以得到一个类似的效果.sh.fun
,.sh.file
并.sh.lineno
在ksh93的。在mksh中,最后有一个LINENO
。
declare
是ksh的bash专用名称typeset
。使用typeset
:它也可以在bash中使用。
Mksh定义local
为的别名typeset
。在ksh93中,您需要使用typeset
(或定义一个别名)。
Mksh没有关联数组(它们计划用于尚未发布的版本)。
我不认为typeset -t
ksh中有bash的(跟踪函数)的完全等效项。
Ksh93没有-e
。
Ksh93和mksh处理bash 中的-e
和-n
选项。Mksh也了解-E
,ksh93不会将其视为选项。在ksh93中,默认情况下,反斜杠扩展处于关闭状态;在mksh中,默认情况下处于启用状态。
Ksh没有提供禁用内置命令的方法。为避免内置,请查找外部命令的路径并显式调用它。
Ksh93有-a
但没有-l
。Mksh都没有。
ksh93和mksh都没有export -n
。typeset +x foo
改为使用,它可以在bash和ksh中使用。
Ksh不会通过环境导出功能。
let
在bash和ksh中是相同的。
这是bash特有的功能。您可以使用while read
循环或命令替换来读取文件并将其拆分为行数组。保重IFS
并保持平衡。这相当于mapfile -t lines </path/to/file
:
IFS=$'\n'; set -f
lines=($(</path/to/file))
unset IFS; set +f
printf
非常相似。我认为ksh93支持bash的所有格式指令。mksh不支持%q
或%(DATE_FORMAT)T
; 在某些安装中,printf
它不是内置的mksh,而是调用外部命令。
printf -v VAR
是特定于bash的,ksh始终打印到标准输出。
有几个bash特定的选项,包括有关readline的所有选项。选项-r
,-d
,-n
,-N
,-t
,-u
是在bash,ksh93的和mksh相同。
您可以使用相同的语法在Ksh93和mksh中将变量声明为只读。如果变量是数组,则需要首先分配给它,然后使用将其设为只读readonly VAR
。在ksh中不能将函数设为只读。
所有的选项set
,并set -o
为POSIX或ksh功能。
shopt
是特定于bash的。无论如何,许多选项都涉及交互式使用。有关某些选项启用的对滚动和其他功能的影响,请参阅下面的“选项”部分。
的这种变体也.
存在于ksh中。在bash和mksh中,source
在之后搜索当前目录PATH
,但是在ksh93中,它与完全等效.
。
该DEBUG
伪信号不mksh实现。在ksh93中,它以不同的方式报告信息,有关详细信息,请参见手册。
在ksh中,type
是的别名whence -v
。在mksh中,type -p
不打印可执行文件的路径,而是打印一条人类可读的消息。您需要使用whence -p COMMAND
。
选件
要模拟dotglob
ksh93中的选项,可以设置FIGNORE='@(.|..)'
。我认为mksh中没有这样的东西。
该extglob
选项实际上始终在ksh中启用。
我认为这在mksh或ksh93中都不存在。它在zsh中(默认行为,除非null_glob
或csh_null_glob
设置)。
Ksh93具有递归glob **/
,已启用set -G
。Mksh没有递归glob。
Ksh93始终在父外壳程序中运行管道的最后一个命令,在bash中,这需要设置lastpipe
选项。Mksh始终在子Shell中运行管道的最后一个命令。
Mksh没有不区分大小写的模式匹配。Ksh93逐个模式支持它:在模式前面加上~(i)
。
Mksh没有这个。Ksh93逐个模式支持它:在模式前面加上~(N)
。
显然,大多数BASH_xxx
变量都不存在于ksh中。$BASHPID
可以用昂贵但可移植的来模拟sh -c 'echo $PPID'
,并且最近已添加到mksh中。BASH_LINE
是.sh.lineno
在ksh93的和LINENO
在mksh。BASH_SUBSHELL
是.sh.subshell
在ksh93的。
Mksh和ksh93都在ENV
启动时提供给定的文件。
EUID
并且UID
在ksh93中不存在。Mksh称他们USER_ID
和KSH_UID
; 它没有GROUPS
。
FUNCNAME
并且FUNCNEST
在ksh中不存在。Ksh93具有.sh.fun
和.sh.level
。用function foo { …; }
(没有括号!)声明的函数在中具有自己的名称$0
。
GLOBIGNORE
在ksh93中存在,但具有不同的名称和语法:称为FIGNORE
,它是单个模式,而不是用冒号分隔的列表。使用@(…|…)
模式。Ksh FIGNORE
包含bash的语法完全不同。
Ksh93和mksh没有类似的东西HOSTTYPE
,MACHTYPE
并且OSTYPE
。也SHELLOPTS
还是TIMEFORMAT
。
Mksh有PIPESTATUS
,但ksh93没有。
Mksh和ksh93具有RANDOM
。