bash
关键字来定义function
函数。有什么区别吗?#!/bin/bash
function foo() {
echo "foo"
}
bar() {
echo "bar"
}
foo
bar
函数
foo
和bar
的调用都成功了,我看不出任何区别。所以我想知道这是否只是为了提高可读性,还是我缺少某些东西... 在其他外壳中,例如
dash
(/bin/sh
与debian / ubuntu中的dash
链接),它会失败当使用function
关键字时。#1 楼
AFAIK没有什么区别,除了第二个版本更便于移植。评论
那是一个巨大的差异,可移植性...我看到了太多的答案,这些答案根本不能在(较旧的)生产系统上运行,并且还有很多选项仅适用于linux。至少要警告一下,这不是最便携的方法……这可能是非常危险的(向tar cf询问某人-/ some / thing | ssh user @ desthost“ cd destinationdir && tar xf-”却没有警告他们先加倍-检查desthost上的tar版本是否会删除“ /”,在某些情况下可能导致灾难...)。例如:如果使用功能tar {#具有安全检查功能的安全tar ...}却忽略了它,...
–奥利维尔·杜拉克(Olivier Dulac)
2013年4月26日15:51
@OlivierDulac我要补充一点,假设sh可以识别function关键字的脚本-通常,假定像ksh和bash这样的shell提供的通用但非标准功能-即使在新的生产系统上也可以正常工作,在同一操作系统的旧版本上。 bash仍然在许多GNU / Linux系统上提供sh,但是一些流行的发行版已将sh用作破折号的符号链接(Debian Almquist SHell)以提高性能。这包括Debian和Ubuntu。
– Eliah Kagan
18年4月11日在12:43
如果不详细说明它的“可移植性”如何确切,答案就没有用。
– ivan_pozdeev
19 Mar 22 '19 at 13:21
如今,当行业在超过99.9%的所有环境中使用bash或等效的shell时,可移植性已不再成为争论。它归结为可读性,它有两个方面:有人说“功能”使它显而易见,从posix标准或其他shell中学习到它的人会说花括号是更明显的样式。最后,在您的小组或公司中选择一个并坚持下去。
–Hubert Grzeskowiak
19年8月26日在14:46
#2 楼
在ksh中引入了function
关键字。传统的Bourne Shell仅具有foo ()
语法,而POSIX仅使foo ()
语法标准化。 Bourne / POSIX语法。在由function
定义的函数中,function
关键字声明一个局部变量:函数退出后,变量的值将重置为进入函数之前的值。使用经典语法,无论是否使用typeset
,变量都具有全局作用域。$ ksh -c 'a=global; f () { typeset a=local; }; f; echo $a'
local
$ ksh -c 'a=global; function f { typeset a=local; }; f; echo $a'
global
ksh的另一个区别是,用
typeset
关键字定义的函数有自己的陷阱。上下文。在执行函数时,将忽略在函数外部定义的陷阱,并且函数内部的致命错误仅会退出函数,而不会退出整个脚本。同样,function
是function
定义的函数中的函数名,但qq1202079q定义的函数中的脚本名。Pdksh不模拟ATT ksh。在pdksh中,无论功能如何,
()
都会创建局部作用域变量,并且没有局部陷阱(尽管使用typeset
确实会产生一些细微的差异-有关详细信息,请参见手册页。)引入了Bash和zsh
function
关键字,用于与ksh兼容。但是,在这些shell中,function
和function foo { … }
严格相同,bash和zsh扩展名foo () { … }
也是如此。 function foo () { … }
关键字始终声明局部变量(当然,typeset
除外),并且陷阱不是局部的(可以通过设置-g
选项在zsh中获得局部陷阱)。评论
应该注意的是,在Bourne shell引入其foo()命令语法之前,已将功能支持添加到Korn Shell中,并且为了兼容性,后来将Bourne语法添加到Korn Shell中。
–StéphaneChazelas
13年4月29日在11:54
#3 楼
foo() any-command
是所有类似Bourne的外壳程序所支持的Bourne语法,但bash
,yash
和posh
的最新版本(仅支持复合命令)。 (尽管ksh
是复合命令,但foo() any-command > redirections
的Bourne shell和AT&T实现不支持any-command
。)foo() any-compound-command
(复合命令的示例:
{ cmd; }
,for i do echo "$i"; done
, (cmd)
...最常用的是{ ...; }
)是任何类似Bourne的外壳以及通常要使用的外壳支持的POSIX语法。
function foo { ...; }
是Korn shell语法,它早于Bourne语法。仅在专门为Korn shell的AT&T实现编写并且需要在那里接受特定处理的情况下,才使用此代码。该语法不是POSIX,但
bash
,yash
和zsh
支持与Korn Shell兼容,尽管这些Shell(以及基于K43 Shell的基于pdksh
的变体)与标准语法没有任何区别。 /> function foo () { ...; }
是no shell的语法,不应使用。它仅偶然地由Korn外壳的基于
bash
,yash
,zsh
和基于pdksh
的变体支持。顺便说一句,它也是awk
函数的语法。 如果我们继续深入下去,
function foo() other-compound-command
(例如
function foo() (subshell)
或function foo() for i do; ... done
)会更糟。它受bash
,yash
和zsh
的支持,但不支持ksh,甚至不支持基于pdksh
的变体。同时:
function foo() simple command
仅受
zsh
支持。评论
Bash中记录了同时包含function关键字和括号的语法。 Bash 4.2及更高版本的手册说,函数是通过语法名()复合命令[重定向]或函数名[[)]复合命令[重定向]声明的。在Bash 4.1.11中,至少降到3.0-beta只是单行[function] name()复合命令[redirection]错误地不包括语法,该语法包括function关键字,但不包括括号,但仍然涵盖了包含function关键字和括号的语法。
– nisetama
16年6月18日在6:48
@nise,关键是bash除了foo(){还可以识别函数foo {以与Korn shell兼容(并且始终具有),因此它可以解释为Korn shell编写的脚本。它也支持函数foo(){,但是没有充分的理由使用该函数。
–StéphaneChazelas
16年6月20日在6:15
@StéphaneChazelas好,我想说有充分的理由使用函数f(){。就是说,就可读性而言,只有英语和英语的任何人都可以将它识别为一种功能,而其中只有一套。
–沮丧的丹尼尔
16年11月25日在1:37
应该是公认的答案。确实很重要定义函数时,切勿将关键字函数与括号()结合使用。
– 4wk_
18年5月7日在11:26
欢迎来到2019,那里只有一个针对Linux / unix自动化脚本的行业实际标准;几乎到处都安装了一个解释器(不包括异国环境):bash。使用所有bash功能编写代码,使用shebang,一切都会好起来的。兼容性的论点是无效的。
–Hubert Grzeskowiak
19年8月26日在14:41
#4 楼
在语义上,这两种形式在Bash中是等效的。从手册页:
Shell函数的声明如下:
name () compound-command [redirection]
function name [()] compound-command [redirection]
这定义了一个名为
name
的函数。保留字功能是可选的。如果提供了函数保留字,则括号是可选的。编辑:我只是注意到这个问题被标记为
posix
。在POSIX sh
中,未使用function
关键字(尽管它是保留关键字)。#5 楼
到目前为止,还有其他几个人已经正确回答了,但是这是我的简要概述:第一个版本仅适用于bash,但您可以在函数名称后省略括号。否则,在bash解释它们之后,它们表示相同的实体。
评论
实际上,第一个版本没有任何意义,只是将其限制为某些shell可接受的语法。当您包含()和function关键字时,shell的行为就像您刚刚做了foo(){...;无论如何,当然,对于无效语法的shell除外。所以你应该执行foo {...; }(如果必须),或者foo(){...; } 除此以外。
–mikeserv
2015年12月1日在8:52
#6 楼
如果没有人说过,则形式function foo() {}
在Korn Shell中无效(至少在KSH 93中)。正确的格式是function foo {}
,不要带双括号。两种格式在BaSH和ZSH中均有效,而ASH(以及扩展名DASH)根本不允许使用function关键字。评论
如果您读了每个单词,您可能会发现StéphaneChazelas的答案涵盖了这个单词(在其他程度上,也是这样)。
–斯科特
20 Mar 2 '20 at 23:34
评论
同样带或不带括号:function baz {echo“ baz”; }。请参阅GreyCat Wiki中的Bashism。