我通常开始(在#!line之后)带有一个带有文件名,概要,用法,返回值,作者,更改日志的注释掉的标题,并且适合80-char行.
所有文档行我都以双重哈希符号开头:“##”,所以我可以轻松地为它们grep,本地var名称前缀为“__”.
谢谢
编辑:关于版本控制的评论:我们svn没问题,但是企业中的另一个部门有一个单独的回购,这是他们的脚本 – 如果没有@author信息,我怎么知道与Q联系的人? javadocs类似的条目甚至在shell上下文中有一些优点,恕我直言,但我可能错了.谢谢你的回复
#!/bin/ksh # # @(#)$Id$ # # Purpose
第三行是一个版本控制标识字符串 – 它实际上是一个SCCS标记’@(#)’的混合体,可以由(SCCS)程序识别什么和一个RCS版本字符串,当文件放在RCS,我用于私人使用的默认VCS. RCS程序ident获取$Id $的扩展形式,可能看起来像$Id:mkscript.sh,v 2.3 2005/05/20 21:06:35 jleffler Exp $.第五行提醒我脚本应该在顶部描述其目的;我用脚本的实际描述替换了这个单词(这就是为什么后面没有冒号的原因).
在那之后,shell脚本基本上没有标准.出现了标准片段,但没有出现在每个脚本中的标准片段. (我的讨论假定脚本是用Bourne,Korn或POSIX(Bash)shell表示法编写的.有一个完整的单独讨论,为什么任何人在#!sigil之后放置C Shell衍生物都是生活在罪中.)
例如,只要脚本创建中间(临时)文件,此代码就会以某种形式或形式出现:
tmp=${TMPDIR:-/tmp}/prog.$$ trap "rm -f $tmp.?; exit 1" 0 1 2 3 13 15 ...real work that creates temp files $tmp.1,$tmp.2,... rm -f $tmp.? trap 0 exit 0
第一行选择一个临时目录,如果用户没有指定替代方法,则默认为/ tmp($TMPDIR被广泛认可并由POSIX标准化).然后,它会创建一个包含进程ID的文件名前缀.这不是一项安全措施;这是一个简单的并发度量,可以防止脚本的多个实例践踏彼此的数据. (为了安全起见,在非公共目录中使用不可预测的文件名.)第二行确保在shell收到任何信号SIGHUP(1),SIGINT(2)时执行’rm’和’exit’命令),SIGQUIT(3),SIGPIPE(13)或SIGTERM(15). ‘rm’命令删除与模板匹配的所有中间文件; exit命令确保状态为非零,表示存在某种错误. ‘陷阱’为0表示如果shell因任何原因退出,也会执行代码 – 它包含标记为“实际工作”的部分中的疏忽.最后的代码然后删除任何幸存的临时文件,然后在退出时解除陷阱,最后以零(成功)状态退出.显然,如果要退出其他状态,可以 – 只需确保在运行rm和trap行之前将其设置在变量中,然后使用exit $exitval.
我通常使用以下命令从脚本中删除路径和后缀,因此我可以在报告错误时使用$arg0:
arg0=$(basename $0 .sh)
error() { echo "$arg0: $*" 1>&2 exit 1 }
如果只有一个或两个错误退出,我不打扰该功能;如果还有,我这样做是因为它简化了编码.我还创建了或多或少精心设计的函数,用于给出如何使用命令的摘要 – 再次,只有在有多个地方才能使用它.
另一个相当标准的片段是一个选项解析循环,使用内置的getopts shell:
vflag=0 out= file= Dflag= while getopts hvVf:o:D: flag do case "$flag" in (h) help; exit 0;; (V) echo "$arg0: version $Revision$($Date$)"; exit 0;; (v) vflag=1;; (f) file="$OPTARG";; (o) out="$OPTARG";; (D) Dflag="$Dflag $OPTARG";; (*) usage;; esac done shift $(expr $OPTIND - 1)
要么:
shift $(($OPTIND - 1))
“$OPTARG”周围的引号处理参数中的空格. Dflag是累积的,但这里使用的符号会丢失参数中的空格.有(非标准的)方法可以解决这个问题.
第一个移位符号适用于任何shell(或者如果我使用back-ticks而不是’$(…)’.第二个工作在现代shell中;甚至可能有替代方括号而不是括号,但是这是有效的,所以我不打算弄清楚那是什么.
现在最后一个技巧是我经常有GNU和非GNU版本的程序,我希望能够选择我使用的.因此,我的许多脚本都使用如下变量:
: ${PERL:=perl} : ${SED:=sed}
然后,当我需要调用Perl或sed时,脚本使用$PERL或$SED.这有助于我在某些行为不同的情况下 – 我可以选择操作版本 – 或者在开发脚本时(我可以在不修改脚本的情况下为命令添加额外的仅调试选项).