本文也即《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的优先级别高于脚本。如果有重名,优先级别依次如下:

  1. Aliases
  2. 关键字,例如function,if,for
  3. Functions
  4. Built-ins,例如cd,type
  5. 在命令搜索路径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 [转]的更多相关文章

  1. Shell入门教程:Shell函数详解

    Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.函数定义 ...

  2. Shell入门教程:Shell函数的返回值

    shell函数返回值一般有3种方式: 1.return语句(默认的返回值) shell函数的返回值可以和其他语言的返回值一样,通过return语句返回. 比如: #!/bin/bash functio ...

  3. (转)Shell函数

    Shell函数类似于Shell脚本,里面存放了一系列的指令,不过Shell的函数存在于内存,而不是硬盘文件,所以速度很快,另外,Shell还能对函数进行预处理,所以函数的启动比脚本更快. 1.  函数 ...

  4. Linux Shell系列教程之(十五) Shell函数简介

    本文是Linux Shell系列教程的第(十五)篇,更多Linux Shell教程请看:Linux Shell系列教程 函数可以将一个复杂功能划分成若干模块,从而使程序结构更加清晰,代码重复利用率更高 ...

  5. Shell函数语法

    Shell函数语法 定义函数: function   函数名(){ 指令... } 调用函数,方法1: 函数名 调用函数,方法2: 函数名  参数一   参数二 return在函数里面使用会跳出函数并 ...

  6. shell 函数

    1 shell函数的定义及其调用 shell函数有两种格式: function name { commands } name() { commands } 其中,name为函数名,commands为函 ...

  7. Shell函数:Shell函数返回值、删除函数、在终端调用函数

    函数可以让我们将一个复杂功能划分成若干模块,让程序结构更加清晰,代码重复利用率更高.像其他编程语言一样,Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: f ...

  8. Javascript学习之函数(function)

    在JS中,Function(函数)类型实际上是对象;每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针. 一 函 ...

  9. Shell函数返回值、删除函数、在终端调用函数

    Shell 也支持函数.Shell 函数必须先定义后使用. Shell 函数的定义格式如下: function_name () { list of commands [ return value ] ...

随机推荐

  1. Linux下安装firefox最新版

    Linux刚安装好的时候,默认是火狐浏览器并且版本比较低,我的系统是CentOS,火狐版本号才31,用yum安装的话版本也不是最新,只要从官方网站下载最新版安装就可以了,方法如下: 首先去火狐主页,中 ...

  2. Light OJ 1253 Misere Nim (尼姆博弈(2))

    LightOJ1253 :Misere Nim 时间限制:1000MS    内存限制:32768KByte   64位IO格式:%lld & %llu 描述 Alice and Bob ar ...

  3. Android Handler leak 分析及解决办法

    In Android, Handler classes should be static or leaks might occur, Messages enqueued on the applicat ...

  4. mysql自增字段重排 或 归零

    由于删除了某些记录行,所以自增字段不连续了.重排或归零的方法:方法1:truncate table 你的表名//这样不但重新定位自增的字段,而且会将表里的数据全部删除,慎用!方法2:delete fr ...

  5. EZ的间谍网络(codevs 4093)

    由于外国间谍的大量渗入,学校安全正处于高度的危机之中.YJY决定挺身而作出反抗.如果A间谍手中掌握着关于B间谍的犯罪证据,则称A可以揭发B.有些间谍收受贿赂,只要给他们一定数量的美元,他们就愿意交出手 ...

  6. Linux C 知识 char型数字转换为int型 int型 转换为Char

    前言 在九度oj做acm的时候,经常会遇到了char类型和int类型相互转化的问题,这里进行一下总结.今后,可能会多次更新博客,因为半年做了很多总结,但是都是保存在word文档上了,现在开始慢慢向CS ...

  7. SQLite中DML DDL DML命令的区别[转]

    总体解释: DML(data manipulation language):       它们是SELECT.UPDATE.INSERT.DELETE,就象它的名字一样,这4条命令是用来对数据库里的数 ...

  8. Hierachy Viewer 使用 monitor命令

    使用 Hierachy Viewer 可视化调试工具 Hierachy Viewer 能很方便地在开发者设计,调试和调整界面时,快速定位问题,解决问题,提高开发效率. Hierarchy Viewer ...

  9. hdu 1542 扫描线求矩形面积的并

    很久没做线段树了 求矩形面积的并分析:1.矩形比较多,坐标也很大,所以横坐标需要离散化(纵坐标不需要),熟悉离散化后这个步骤不难,所以这里不详细讲解了,不明白的还请百度2.重点:扫描线法:假想有一条扫 ...

  10. Action类为何要 extends ActionSupport

    我做的时候,我的action是继承ActionSupport的 Struts 2的Action无须实现任何接口或继承任何类型,普通的POJO类就可以用做Action类,但是,我们为了方便实现Actio ...