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

  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_。如果一个变量后面紧跟着_、字母或者数字,安全起见,需要用大括号。

时间: 2024-09-20 05:28:14

Shell 函数 function [转]的相关文章

shell函数和脚本的综合应用

1.shell函数:shell允许将一组命令集或语句形成一个可用块,这些块称为shell函数. 函数由两部分组成:函数标题.函数体. 标题是函数名.函数体是函数内的命令集合. 标题名应该唯一:如果不是,将会混淆结果,因为脚本在查看调用脚本前将首先搜索函数调用相应的shell. 2.定义函数的格式为: 函数名(){ 命令1 ... } 如果愿意,可在函数名前加上关键字function,这取决于使用者. function函数名() { 命令1  ... } 3.举例: 例1:删除文件中的空行 这个脚

Linux下如何编写和使用自定义的Shell函数和函数库

在 Linux 系统下,Shell 脚本可以在各种不同的情形下帮到我们,例如展示信息,甚至 自动执行特定的系统管理任务,创建简单的命令行工具等等. 在本指南中,我们将向 Linux 新手展示如何可靠地存储自定义的 shell 脚本,解释如何编写 shell 函数和函数库,以及如何在其它的脚本中使用函数库中的函数. Shell 脚本要存储在何处 为了在执行你自己的脚本时不必输入脚本所在位置的完整或绝对路径,脚本必须被存储在 $PATH 环境变量所定义的路径里的其中一个. 使用下面的命令可以查看你系

如何编写和使用自定义的 Shell 函数和函数库

在 Linux 系统下,Shell 脚本可以在各种不同的情形下帮到我们,例如展示信息,甚至 自动执行特定的系统管理任务,创建简单的命令行工具等等. 在本指南中,我们将向 Linux 新手展示如何可靠地存储自定义的 shell 脚本,解释如何编写 shell 函数和函数库,以及如何在其它的脚本中使用函数库中的函数. Shell 脚本要存储在何处 为了在执行你自己的脚本时不必输入脚本所在位置的完整或绝对路径,脚本必须被存储在 $PATH 环境变量所定义的路径里的其中一个. 使用下面的命令可以查看你系

ECMAScript中函数function类型

  这篇文章主要介绍了ECMAScript中函数function类型的相关资料,需要的朋友可以参考下 说起来ECMAScript中上面最有意思,我想那莫过于函数了,有意思的根源,则在于函数实际上是对象.每个函数都是Function类型的实例,而且都与其他引用类型一样具有属性和方法.由于函数是对象,因此函数名实际上也是一个指向函数对象的指针,不会与某个函数绑定.函数通常是使用函数声明语法定义的,如下例子: 代码如下: function sum(num1,num2) { return num1+nu

bash-在shell脚本include的shell函数中出现的特殊符号NO_EXPORT:+-n什么意思

问题描述 在shell脚本include的shell函数中出现的特殊符号NO_EXPORT:+-n什么意思 config_get [] config_get config_get() { case ""$3"" in") eval echo ""${CONFIG_${1}_${2}:-${4}}"";; *) eval export ${NO_EXPORT:+-n} -- ""${1}=${CON

浅析JS中对函数function的理解(基础篇)_javascript技巧

正文:我们知道,在js中,函数实际上是一个对象,每个函数都是Function类型的实例,并且都与其他引用类型一样具有属性和方法.因此,函数名实际上是指向函数对象的指针,不与某个函数绑定.在常见的两种定义方式(见下文)之外,还有一种定义的方式能更直观的体现出这个概念: var sum = new Function("num1", "num2", "return num1 + num2"); //不推荐 Function的构造函数可以接收任意数量的参

深入理解javascript中的立即执行函数(function(){…})()_基础知识

javascript和其他编程语言相比比较随意,所以javascript代码中充满各种奇葩的写法,有时雾里看花,当然,能理解各型各色的写法也是对javascript语言特性更进一步的深入理解. ( function(){-} )()和( function (){-} () )是两种javascript立即执行函数的常见写法,最初我以为是一个括号包裹匿名函数,再在后面加个括号调用函数,最后达到函数定义后立即执行的目的,后来发现加括号的原因并非如此.要理解立即执行函数,需要先理解一些函数的基本概念.

Javascript自执行匿名函数(function() { })()的原理浅析_javascript技巧

函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数指没有指定函数名或指针的函数,自执行匿名函数只是其中一种,下文中称这种函数为:自执行函数 下面是一个最常见的自执行函数: // 传统匿名函数 (function() { alert('hello'); })(); 这段代码的执行效果就是在页面再载入时弹出:"hello" 是什么促使它自动执行的?,来看下面的代码 // 在传统写法上去掉小括号,并在前面加上运算符 ~,!,+,- ~function(){

prll 0.6.1发布 shell函数并行执行工具

prll是一个并行执行shell函数的工具.它提供了一个方便的界面来并行执行单个任务,通过多个数据文件或其他类型的数据作为一个shell函数的参数,简单充分利用多核/多处理器的机器.prll不只是在shell脚本中的使用,也能用于交互式shell,为了使用者的方便,它也可以作为一个shell函数.prll能够使用C编写的辅助程序自动管理项目. prll 0.6.1版本添加prll_seq,是一个GNU SEQ的简单替代品.五个locks可以为用户提供他们需要同步函数.增加了另一种辅助功能,以纾缓