Shell 函数 function [转]
本文也即《Learning the bash Shell》3rd Edition的第四章Basic Shell Programming之读书笔记,但我们将不限于此。
运行shell脚本程序
一个包含shell命令的脚本就是一个shell程序,例如.bash_profile。我们创建shell脚本,允许的时候可以通过两种方式:一、source ;二、只敲入文件名,按回车就可以执行,这种方式更为便捷。我们需要将文件放置在命令搜索路径下(在Linux Bash学习(六):设置环境参数 中介绍),否则需要指出绝对路径,例如在当前目录,使用./, 另外我们还需要将文件的权限设置为可执行文件,采用$ chmod +x 的方式设置,+x表示增加执行的权限。
这两种方式是由区别的。采用source就如同我们在terminal上敲入命令一样。采用后一种方式,系统运行一个子进程,它copy了shell,叫作subshell,主shell等待子shell运行结束。另外我们设置让子shell后台运行,即 & 。
这个区别还体现在export 的使用上,例如我们设置aa=hello, world,这个变量在命令行中有效,但是在脚本文件是无效,需要使用export aa='hello, world ' 来保证在subprocess中也是有效,即可以用于脚本文件中。
函数Functions
使用function有两个原因:一、function存放在系统的内存,所以调用的使用,效率更高;二、更好地组织长的bash,使之模块化。定义function,有两个方式:
function functname {
shell commands
}
functname
( ){
shell commands
}
上面两种方式没有区别。我们可以通过unset –f functname
来删除函数的定义。 当我们定义一个function,将它的名字和定义存放在内存,我们可以象调用shell脚本的方式来调用它。我们通过declare -f
来查看当前已经定义的function情况,如果我们只查看function名字,使用declare -F
。我们可以在命令行中敲入一个function来检验,如果我们将function定义在一个文件中,例如在文件a,可以用source a
来是指生效,如果我们将a设定为可执行文件,这function的定义只在该脚本中有效,如果需要使之仍然有效,保留环境,采用$.
./a
,而不只是$./a
。
Function作为一个整体运行,不会分割为子进程,此外Function的优先级别高于脚本。如果有重名,优先级别依次如下:
- Aliases
- 关键字,例如function,if,for
- Functions
- Built-ins,例如cd,type
- 在命令搜索路径PATH下的脚本和可执行文件
如果我们需要查看所使用命令属于哪种,用type name
,例如aa是个alias(表示pwd),同样我们也定义了它作为一个function,根据优先级别,aa优先作为alias,type aa,我们可以得到aa is aliased to ‘pwd’,可以用type –a(或者-all) name
,来查看aa代表的所有含义。如果使用非最优先级别或者重新定义优先级别的先后顺序,在书的第7章,我们先放下此话题不表。上述的命令将显示详细内容,可以用type –t name
的方式,查看类型,将返回alias | keyword | function | builtin | file。type –p name
用于查看file的路径,如果类型不是file将没有返回,而type –P name
则强制查找file的路径。例如一个重名,它是一个alias,也是一个在PATH目录下的可执行文件。-p则没有返回,-P这返回文件的绝对路径。
位置参数
在脚本命令中,有时是带有参数,这些参数可以通过位置变量来获取。例如我们有个脚本文件叫做test,执行的使用带参数,即$./test
param1 param2
param3,我们可以在脚本中来获取参数的值。使用$N,其中$0是./test,它表示执行的脚本名字,剩余的为所带参数,$1为param1,$2
为param2,如此类推,如果N大于实际参数的数目,为空。我们一般将位置变量是从$1开始。
$*
表示所有参数组成的一个字符串,在上面的例子中,为param1 param2 param3。这些参数之间的间隔是IFS的首个字母即空格,IFS包括TAB,空格,换行等字符。
$@
等同于"$1" "$2"... "$N"。
$#
表示参数的个数,在上面的例子中为3。
这些位置变量都是只读,不能赋值的。$*和$@非常相似,一般而言输出是一样的。$*的分割是在IFS的字符,我们可以重新定义IFS的字符,将导致不同的输出结果。我们在脚本中定义IFS=,
,即可将输出改用逗号做为分割,这个脚本名字为a,运行./a h1 h2,则$#=2,表示有两个参数,$@为h1 h2,$*为h1,h2
,输出结果不一样。
同样这些位置变量可以用于function中,并对function的参数进行体现,即是local的,属于function,但是$0是例外,他表示脚本的名字,这个参数是gobal的。下面是个例子。脚本a内容如下:
hello ()
{
var="hello";
echo "Hello"
echo "Hello: param num is $#"
echo "Hello: $@"
echo "Hello: $*"
echo "Hello: $0 $1 $2"
echo "Hello: var=$var";
}
var="hello";
echo "main: param num is $#"
echo "main: $@"
echo "main: $*"
echo "main: $0 $1 $2"
echo "main: var=$var";
hello h1 h2
我们执行./a a1 a2 a3
main: param num is 3
main: a1 a2 a3
main: a1 a2 a3
main: ./a a1 a2
main: var=main
Hello
Hello: param num is 2
Hello: h1 h2
Hello: h1 h2
Hello: ./a h1 h2
Hello: var=hello
除了$0外,所有的位置变量都是local的,即如果在function中,则在function中有效。同样,用户定义的其他变量,也是
local的,即在最近的{}内有效。见上面例子中的用户变量var。我们可以在function中定义var加上local来特别标明这是一个本地参
数,上面的例子在函数hello,可以使用local var=”hello”
。
避免歧义的变量定义
实际上我们使用$varname,是${varname}
的一个缩写。有时我们不能使用缩写,例如我们需要获取第10个参数,使用$10,这实际是第一个参数加上“0”,需要使用${10}。又例如,我们希望显
示进程号,并在后面仅跟_、字母或者数字,我们使用echo $UID_,会见UID_看作一个整体,即echo
${UID_},因此是空,需要使用echo
${UID}_,假设进程号为1000,则为1000_。如果一个变量后面紧跟着_、字母或者数字,安全起见,需要用大括号。
Shell 函数 function [转]的更多相关文章
- Shell入门教程:Shell函数详解
Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.函数定义 ...
- Shell入门教程:Shell函数的返回值
shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...
- (转)Shell函数
Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1. 函数 ...
- Linux Shell系列教程之(十五) Shell函数简介
本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...
- Shell函数语法
Shell函数语法 定义函数: function 函数名(){ 指令... } 调用函数,方法1: 函数名 调用函数,方法2: 函数名 参数一 参数二 return在函数里面使用会跳出函数并 ...
- shell 函数
1 shell函数的定义及其调用 shell函数有两种格式: function name { commands } name() { commands } 其中,name为函数名,commands为函 ...
- Shell函数:Shell函数返回值、删除函数、在终端调用函数
函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高.像其他编程语言一样,Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: f ...
- Javascript学习之函数(function)
在JS中,Function(函数)类型实际上是对象;每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针. 一 函 ...
- Shell函数返回值、删除函数、在终端调用函数
Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: function_name () { list of commands [ return value ] ...
随机推荐
- LSB 简介
前 Linux 的发行版非常繁多,为了促进 Linux 不同发行版间的兼容性,LSB(Linux Standards Base)开发了一系列标准,使各种软件可以很好地在兼容 LSB 标准的系统上运行, ...
- 【Hadoop】史上最全 Hadoop 生态 全景图
- 【Spring】Spring系列2之bean的配置
2.bean的配置 2.1.IOC概述 2.2.bean的获取 2.3.依赖注入方式 2.4.属性注入细节 内部bean,不需要ID,ID无效,外部不能引用: 2.5.集合属性注入 2.6.使用p命名 ...
- hadoop(一):深度剖析hdfs原理
在配置hbase集群将 hdfs 挂接到其它镜像盘时,有不少困惑的地方,结合以前的资料再次学习; 大数据底层技术的三大基石起源于Google在2006年之前的三篇论文GFS.Map-Reduce. ...
- 获取网页文档的URL和连接来源
<script type="text/javascript">document.write("链接来源:"+document.referrer+&q ...
- css行内样式
<title>归园田居</title> </head> <body> <h2>归园田居</h2> <p>种豆南山下, ...
- poj 1625 (AC自动机好模版,大数好模版)
题目 给n个字母,构成长度为m的串,总共有n^m种.给p个字符串,问n^m种字符串中不包含(不是子串)这p个字符串的个数. 将p个不能包含的字符串建立AC自动机,每个结点用val值来标记以当前节点为后 ...
- jsp页面之间传参用el表达式获取
jsp页面之间传参用el表达式获取 参数方法:${param.参数名} session方法:${session.变量名}
- mybatis中的oracle和mysql分页
这段时间一直在用mybatis+spring+springMVC的框架,总结点东西吧. mybatis的oracle分页写法: <?xml version="1.0" enc ...
- cocos2dx创建sprite的多种方法
方法一 最常用,也是最简单的一种方法 CCSprite *bg=CCSprite::create(,,,)); bg->setAnchorPoint(ccp(,)); bg->setPos ...