• 1. LINUX的编程常识 武汉大学计算机学院 李文海 lwhaymail@21cn.com
  • 2. shell 函数在shell中可以定义函数。函数实际上也是由若干条shell命令组成的,因此它与shell程序形式上是相似的,不同的是它不是一个单独的进程,而是shell程序的一部分。函数由两部分组成:函数名和函数体。 函数定义的格式为: 函数名() { 命令集合 } 或者 function 函数名() { 命令集合 }
  • 3. Shell函数与脚本的区别Shell函数和shell程序比较相似,它们的区别在于: Shell程序在子Shell中运行 而Shell函数在当前Shell中运行。因此在当前Shell中可以看到Shell函数对变量的修改。 函数的定义和使用: 可将函数放在脚本文件中作为它的一部分; 可放在只包含函数的单独文件中; 可在交互式环境下定义函数。
  • 4. 在交互式环境下定义和使用函数例如: $ dir() { > ls -l > } $ 定义该函数后,若在$后面键入dir,其显示结果同ls -l的作用相同。 $ dir 该dir函数将一直保留到用户从系统退出,或执行了如下所示的unset命令: $ unset dir 
  • 5. 在脚本中定义及使用函数函数在使用前必须定义,因此应将函数定义放在脚本开始部分,直至shell首次发现它后才能使用。 调用函数仅使用其函数名即可。例如:$ cat func1 #!/bin/sh # func1 hello() { echo "Hello there today's date is `date`" } echo "now going to the function hello" hello echo "back from the function"
  • 6. 在脚本中定义及使用函数运行脚本,结果为: $ func1 now going to the function hello Hello there today's date is Sun Jun 6 10:46:59 GMT 2006 back from the function 上例中函数定义于脚本顶部。可以在脚本中使用函数名hello调用它。 函数执行后,控制返回函数调用的下一条语句,即语句echo “back from the function”
  • 7. 向函数传递参数向函数传递参数就像在脚本中使用位置变量$1,$2,$3...$9向脚本传递参数一样。 函数返回有以下情况: 函数正常执行到函数末尾,然后返回脚本中调用函数的部分。 使用return返回脚本中函数调用的下一条语句,可以带返回值。0为无错误,1为有错误。 其格式为: return 从函数中返回,用最后状态命令决定返回值。 return 0 无错误返回。 return 1 有错误返回
  • 8. 向函数传递参数例#!/bin/bash #hellofun function check_dir(){   if [ -d $1 ] then return 0 else return 1 }
  • 9. 函数返回值测试例check_dir $FILENAME # a function call and check if [ $? = 0 ] # use the last status command now to test then echo "All is OK" else echo " Something went wrong!" fi 最好在if语句里使用函数调用,以增加可读性。 if check_dir $FILENAME; then echo "All is OK" else echo "Something went wrong !" fi
  • 10. 在shell中使用函数可以将经常使用的函数存入函数文件,然后将函数文件载入shell。 文件名可任意选取,但最好与相关任务有某种联系。例如:functions.main 一旦函数文件载入shell,就可以在命令行或脚本中调用函数。可以使用set命令查看所有定义的函数,其输出列表包括已经载入shell的所有函数。 若要改动函数,首先用unset命令从shell中删除函数。改动完毕后,再重新载入此文件。
  • 11. 在shell中使用函数——创建函数文件下面创建包容函数的文件并将之载入shell,进行测试,再做改动,之后再重新载入。函数文件名为functions.main,内容如下: $pg functions.main #!/bin/sh #functions.main findit() { if [ $# -lt 1 ] ; then echo "Usage:findit file" return 1 fi find / -name $1 –print }
  • 12. 在shell中使用函数——载入函数定位文件格式为: . filename #注意这里的文件名要带正确路径 文件已创建好后,要将它载入shell,使用如下命令: $ . functions.main 注意,此即<点> <空格> <文件名>,现在文件应该已载入shell。如果仍有错误,则应该仔细检查是否键入了完整路径名。
  • 13. 在shell中使用函数——检查载入函数使用set命令检查函数是否已载入。set命令将在shell中显示所有的载入函数。 $ set findit=( ) { if [ $# -lt 1 ]; then echo "usage :findit file"; return 1 fi find / -name $1 -print } …
  • 14. 在shell中使用函数——执行shell函数要执行函数,简单地键入函数名即可: $ findit groups /usr/bin/groups /usr/local/backups/groups.bak
  • 15. 在shell中使用函数——删除shell函数现在对函数做一些改动。首先删除函数,使其对shell不可用。使用unset命令完成此功能,其命令格式为: unset function_name $ unset findit 如果现在键入set命令,函数将不再显示。
  • 16. 在shell中使用函数——编辑shell函数编辑函数functions.main,加入for循环以便脚本可以从命令行中读取多个参数。改动后函数脚本如下: $ pg functions.main #!/bin/sh findit( ) { # findit if [ $# -lt 1 ]; then echo "usage "findit file" return 1 fi for loop do find / -name $loop -print done }
  • 17. 在shell中使用函数——再次执行shell函数再次定位函数 $ . /functions.main 现在执行改动过的findit函数,输入两个参数: $ findit LPSO.dOC passwd /usr/local/accounts/LPSO.doc /etc/passwd …
  • 18. 在shell中使用函数——变量输入以下脚本询问名,然后是姓。 $ pg func2 #!/bin/sh # func2 echo -n "What is your first name :" read F_NAME echo -n "What is your surname :" read S_NAME
  • 19. 在shell中使用函数——变量输入要求输入字符必须只包含字母,利用函数实现这一点。 char_name() { #to call : char_name string _LETTERS_ONLY=$1 _LETTERS_ONLY=` echo $1|awk ‘{if ($0~/[^a-z A-Z]/) print “1”}’ ` if [ “$_LETTERS_ONLY” != “”] then return 1 #errors else return 0 # contains only chars } awk 命令利用一组用户提供的指令来将一组文件和用户提供的扩展正则表达式比较,一次一行。 awk 命令的模式搜索比 grep 命令的搜索更常用,且它允许用户在输入文本行上执行多个操作。 awk中$0表示当前记录,~表示匹配
  • 20. 在shell中使用函数——变量输入$ pg func2 #!/bin/sh char_name( ) # char_name # to call: char_name string # check if $1 does indeed contain only characters a-z,A-Z { # assign the argurment across to new variable _LETTERS_ONLY=$1 _LETFERS_ONLY=`echo $1|awk ‘{if ($0~/[^a-z A-Z]/) print "1"}’ ` if [ "$_LETFERS_ONLY" != "" ] then return 1 # oops errors else return 0 # contains on]y chars fi } name_errorO # display an error message { echo " $@ contains errors,it must contains only letters" }
  • 21. 在shell中使用函数——变量输入while : do echo -n "What is your first name :" read F_NAME if char_name $F_NAME then break # all ok breakout else name_error $F_NAME fi done while : do echo -n "What is your surname :" read S_NAME if char_name $S_NAME then break # all ok breakout else name_error $S_NAME fi done
  • 22. 在shell中使用函数——变量输入$ func2 What is your first name :Davi2d Davi2d contains errors, it must contain only letters What is your first name :David What is your surname :Tanslay1 Tansley1 contains errors, it must contain only letters What is your surname :Tanslay
  • 23. 在shell中使用函数——测试目录存在拷贝文件时,测试目录是否存在是常见的工作之一。以下函数测试传递给函数的文件名是否是一个目录。因为此函数返回时带有成功或失败取值,可用if语句测试结果。 函数如下:
  • 24. 在shell中使用函数——测试目录存在is_it_a_directory() { # is_it_a_directory # to call:is_it_a_directory directory_name if [ $# -lt 1 ];then echo "is_it_a_directory:I need an argument" return 1 fi # is it a directory? _DIRECTORY_NAME=$1 if [ ! -d $_DIRECTORY_NAME ]; then #no it is not return 1 else #yes it is return 0 fi }
  • 25. 在shell中使用函数——测试目录存在要调用函数并测试结果,可以使用: echo -n “enter destination directory:” read DIREC if is_it_a_directory $DIREC then : else echo “$DIREC does not exist,create it now ? [y..n]” … fi