本文也即《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. php自定义函数call_user_func和call_user_func_array详解

    看UCenter的时候有一个函数call_user_func,百思不得其解,因为我以为是自己定义的函数,结果到处都找不到,后来百度了一下才知道call_user_func是内置函 call_user_ ...

  2. ssh连接慢的问题的解决?

    <1>群中同学遇到的问题,我之前在uuwatch也遇到了同样的问题? 问个问题师兄们 突然之间 公司服务器连接很慢 连一个shell需要10几秒钟 服务器就在公司全是内网服务器, 我也不知 ...

  3. 【云计算】Docker云平台—Docker进阶

    Docker云平台系列共三讲,此为第二讲:Docker进阶 参考资料: 五个Docker监控工具的对比:http://www.open-open.com/lib/view/open1433897177 ...

  4. Shortest Word Distance

    Given a list of words and two words word1 and word2, return the shortest distance between these two ...

  5. Django对静态文件的处理——部署阶段

    参考:http://blog.makto.me/post/2012-11-09/static-files-in-django-deployment HTML模板中的用法: {% load static ...

  6. AngularJS服务中serivce,factory,provider的区别

    Angular服务是一个由服务工厂创建的单例对象.这些服务工厂是由 service provider 依次创建的.而service providers是构造函数.它们必须包含一个$get属性用于在实例 ...

  7. mysql lower,upper实现大小写

    mysql的lower和uppper函数可以将指定字符串转换为小写和大写 select lower('OutSpringTd') as lowerCase, upper('OutSpringTd') ...

  8. ecshop绕过验证码暴力破解

    若验证码不匹配,并没有销毁当前验证码   所以就可以一次请求验证码图片后,只要不再刷新验证码就可以一直使用  1.获取正确的验证码   2. 1 2 3 4 5 6 7 8 9 10 11 12 13 ...

  9. mysql修改表的存储引擎(myisam<=>innodb)

    查看当前数据库的所支持的数据库引擎以及默认数据库引擎 mysql> show engines; +--------------------+---------+----------------- ...

  10. (转)浅谈MD5加密算法中的加盐值(SALT)

    我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码. 加Salt可以一定程度上解决这一问题.所谓加Salt方法,就 ...