shell函数
2013-06-08 21:55
162 查看
1、格式
function 函数名 ()
{
命令1
...
}
2、脚本中定义并使用函数
#!/bin/bash
#func1
hello ()
{
echo "Hello there today's date is `date`"
}
echo "now going to the function hello"
hello
echo "back from the function"
3、向函数传递参数
一般使用位置变量($1,$2...$9),调用参数的转换格式如下:_FILENAME或_filename(下划线加变量名)
4、从调用函数中返回
两种处理:
正常执行到函数末尾,返回脚本中调用函数的控制部分;
return返回脚本中函数调用的下条语句,可带返回值,如下
return --- 函数中返回,用最后状态命令决定返回值
return 0 --- 无错误返回
return 1 --- 有错误返回
5、函数返回值测试
通过最后状态命令测试
check_it_is_a_directory $FILENAME;
if [ $? = 0 ]
then
echo "all is ok"
else
echo "something went wrong!"
fi
或使用if测试返回0或1
if check_it_is_a_directory $FILENAME; then
echo "all is ok"
else
echo "something went wrong!"
fi
6、shell中使用函数
set命令可查看所有定义函数,包括已载入shell的所有函数;改动函数需用unset删除函数(非真正删除,仅对与shell或脚本不可利用),改完再重新载入此文件。
7、创建函数文件
创建包容函数的函数文件并载入shell,函数名为functions.main,如下:
#!/bin/bash
#functions.main
#
#findit: this is front end for the basic find command
findit()
{
if [ $# -lt 1 ]; then
echo "usage : findit file"
return 1
fi
find / -name $1 -print
}
8、定位文件
格式 . pathname/filename
将文件载入shell,如
. functions.main(点+空格+文件名(目录名+文件名))
9、检查载入函数
set命令确保函数已载入
set | grep findit可查看到载入函数findit
10、shell函数修改、删除、集中
删除函数使其对shell不可利用
unset function_name
set命令检查确认
编辑函数functions.main,加入for循环以便脚本可从命令行中读取多个参数
#!/bin/bash
#functions.main
#
#findit: this is front end for the basic find command
findit()
{
if [ $# -lt 1 ]; then
echo "usage : findit file"
return 1
fi
for loop
do
find / -name $1 -print
done
}
11、脚本中或文件中调用函数
脚本中调用函数:
#!/bin/bash
#function file
is_it_a_directory()
{
_DIRECTORY_NAME=$1
if [ $# -lt 1 ]; then
echo "is_it_a_directory: I need a directory name to check"
return 1
fi
if [ ! -d $_DIRECTORY_NAME ]; then
return 1
else
return 0
fi
}
error_msg()
{
echo -e "\007"
echo $@
echo -e "\007"
return 0
}
echo -n "enter destination directory :"
read DIREC
if is_it_a_directory $DIREC
then :
else
error_msg "$DIREC does not exist...creating it now"
mkdir $DIREC > /dev/null 2>&1
if [ $? != 0 ]
then
error_msg "could not create directory:: check it out!"
exit 1
else :
fi
fi
echo "extracting files..."
从函数文件中调用函数:
将函数is_it_a_directory放入到function.sh函数文件中,如下:
#!/bin/bash
#functions.sh
#main script functions
is_it_a_directory()
{
_DIRECTORY_NAME=$1
if [ $# -lt 1 ]; then
echo "is_it_a_directory: I need a directory name to check"
return 1
fi
if [ ! -d $_DIRECTORY_NAME ]; then
return 1
else
return 0
fi
}
error_msg()
{
echo -e "\007"
echo $@
echo -e "\007"
return 0
}
编写脚本调用该文件中的函数需要文件定位,如: 点+空格+函数文件(目录+函数文件),如以下脚本中的调用:
#!/bin/bash
#direc_check
#source the function file function.sh
#that's a <dot><space><forward slash>
. home/test/script/function/function.sh
echo -n "enter destination directory :"
read DIREC
if is_it_a_directory $DIREC
then :
else
error_msg "$DIREC does not exist...creating it now"
mkdir $DIREC > /dev/null 2>&1
if [ $? != 0 ]
then
error_msg "could not create directory:: check it out!"
exit 1
else :
fi
fi
echo "extracting files..."
12、定位文件不仅用于函数
也包含组成配置文件的全局变量
如,先定义个配置文件backfunc,然后从另个脚本readfuc中通过定位文件调用该配置文件中的参数,如下:
#!/bin/bash
#name:backfunc
_CODE="comet"
_FULLBACKUP="yes"
_LOGFILE="/logs/backup/"
_DEVICE="/dev/rmt/0n"
_INFORM="yes"
_PRINT_STATS="yes"
通过定位文件调用函数的脚本如下:
#!/bin/bash
#readfuc
if [ -r backfunc ]; then
. backfunc
else
echo "`basename $0` cannot locate backfunc file"
fi
echo -n "Enter the code name : "
read CODE
if [ "${CODE}" != "${_CODE}" ]; then
echo "wrong code...exiting...will use defaults"
exit 1
fi
echo "The enviroment config file reports"
echo "full backup required :$_FULLBACKUP"
echo "the logfile is :$_LOGFILE"
echo "the device to backup to is :$_DEVICE"
echo "you are to be informed by mail :$_INFORM"
echo "a statistic report to be printed:$_PRINT_STATS"
13、函数举例
(1) 变量输入字符判断,如下:
#!/bin/bash
#func2
char_name()
{
_LETTERS_ONLY=$1
_LETTER_ONLY=`echo $1 | awk '{if($0~/[^a-zA-Z]/) print "1"}'`
if [ "$_LETTER_ONLY" != "" ]
then
return 1
else
return 0
fi
}
name_error()
{
echo "$@ contain erros, it must cotain only letters"
}
while :
do
echo -n "entry your first name :"
read F_NAME
if char_name $F_NAME
then
break
else
name_error $F_NAME
fi
done
while :
do
echo -n "entry your second name :"
read S_NAME
if char_name $S_NAME
then
break
else
name_error $S_NAME
fi
done
(2) 提示Y或N的处理
#!/bin/bash
#continue_prompt
continue_prompt()
{
_STR=$1
_DEFAULT=$2
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y...N] [$_DEFAULT]:"
read _ANS
if [ "$_ANS" = "" ]; then
: ${_ANS:=$_DEFAULT}
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
case $_ANS in
y|Y|Yes|YES) return 0 ;;
n|N|No|NO) return 1 ;;
*) echo "answer either Y or N,default is $_DEFAULT" ;;
esac
echo $_ANS
done
}
然后文件调用函数
#!/bin/bash
. continue_prompt
if continue_prompt "Do your want to delete the var filesystem" "N"; then
echo "Are you nuts!!"
else
echo "Phew! what a good answer"
fi
(3) 通过用户名寻找ID
定义函数文件
#!/bin/bash
#who_is
who_is()
{
if [ $# -lt 1 ]; then
echo "whois : need user id's please"
return 1
fi
for loop
do
_USER_NAME=`grep $loop /etc/passwd | awk -F: '{print $4}'`
if [ "$_USER_NAME" = "" ]; then
echo "whois: sorry cannot find $loop"
else
echo "$loop is $_USER_NAME"
fi
done
}
脚本调用函数
#!/bin/bash
. who_is
echo "`who_is test see oracle`"
(4) 打印出文本文件行数
#!/bin/bash
#numberfile
numberfile()
{
_FILENAME=$1
if [ $# -lt 1 ]; then
echo "need a filename to number"
return 1
fi
loop=1
while read LINE
do
echo "$loop $LINE"
loop=`expr $loop + 1`
done < $_FILENAME
}
调用该函数文件
#!/bin/bash
. numberfile
numberfile ccc
(5) 大小写转换
定义函数文件
#!/bin/bash
str_to_upper()
{
_STR=$1
if [ $# -ne 1 ]; then
echo "need an string to convert"
return 1
fi
echo $@ | tr '[a-z]' '[A-Z]'
}
脚本调用
#!/bin/bash
. str_to_upper
str_to_upper asdfajkjqke
(6) 判断字符串是否为大写
函数文件
#!/bin/bash
#is_upper
is_upper()
{
if [ $# -ne 1 ]; then
echo "is_upper: I need a string to test OK"
return 1
fi
_IS_UPPER=`echo $1|awk '{if($0~/[^A-Z]/) print "1"}'` 换成 _IS_LOWER=`echo $1|awk '{if($0~/[^a-z]/) print "1"}'` 即是检测小写
if [ "$_IS_UPPER" != "" ]
then
return 1
else
return 0
fi
}
调用脚本
#!/bin/bash
. is_upper
echo -n "entry your name:"
read NAME
if is_upper $NAME; then
echo "Great it is upper case!"
else
echo "it's not upper!"
fi
(7) 字符串长度判断
函数文件
#!/bin/bash
#check_length
check_length()
{
_STR=$1
_MAX=$2
if [ $# -ne 2 ]; then
echo "I need string and max length"
return 1
fi
_LENGTH=`echo $1|awk '{print length($1)}'`
if [ "$_LENGTH" -gt "$_MAX" ]; then
return 1
else
return 0
fi
}
脚本调用
#!/bin/bash
. check_length
while :
do
echo -n "Enter your fisrt name :"
read NAME
if check_length $NAME 10
then
break
else
echo "the name field is too long 10 characters max"
fi
done
wc命令的缺点,会将空格部分也做为字符串的长度来计算
(8) MONTHS显示
函数文件
#!/bin/bash
months_test()
{
_MONTHS=$1
if [ $# -ne 1 ]; then
echo "months: I need a number 1 to 12 "
return 1
fi
case $_MONTHS in
1|01|Jan)_FULL="January" ;;
2|02|Feb)_FULL="February" ;;
3|03|Mar)_FULL="March" ;;
4|04|Apr)_FULL="April" ;;
5|05|May)_FULL="May" ;;
6|06|Jun)_FULL="June" ;;
7|07|Jul)_FULL="July" ;;
8|08|Aug)_FULL="August" ;;
9|09|Sep|Sept)_FULL="September" ;;
10|Oct)_FULL="October" ;;
11|Nov)_FULL="November" ;;
12|Dec)_FULL="December" ;;
*) echo "months: Unknown month"
return 1
;;
esac
echo $_FULL
}
脚本调用
#!/bin/bash
. months_test
MY_MONTHS=`months_test 02`
echo "the report for Month and $MY_MONTHS"
(9) chop函数,截取部分字符串
函数文件
#!/bin/bash
chop()
{
_STR=$1
_CHOP=$2
CHOP=`expr $_CHOP + 1`
if [ $# -ne 2 ]; then
echo "need a string and an character to chop"
return 1
fi
_LENGTH=`echo $_STR|awk '{print length($0)}'`
if [ "$_LENGTH" -lt "$_CHOP" ]; then
echo "need more characters than there are in the string"
return 1
fi
echo $_STR|awk '{print substr($1,'$CHOP')}'
}
脚本调用
#!/bin/bash
. chop
CHOPED=`chop "1234567890" 5`
echo $CHOPED
function 函数名 ()
{
命令1
...
}
2、脚本中定义并使用函数
#!/bin/bash
#func1
hello ()
{
echo "Hello there today's date is `date`"
}
echo "now going to the function hello"
hello
echo "back from the function"
3、向函数传递参数
一般使用位置变量($1,$2...$9),调用参数的转换格式如下:_FILENAME或_filename(下划线加变量名)
4、从调用函数中返回
两种处理:
正常执行到函数末尾,返回脚本中调用函数的控制部分;
return返回脚本中函数调用的下条语句,可带返回值,如下
return --- 函数中返回,用最后状态命令决定返回值
return 0 --- 无错误返回
return 1 --- 有错误返回
5、函数返回值测试
通过最后状态命令测试
check_it_is_a_directory $FILENAME;
if [ $? = 0 ]
then
echo "all is ok"
else
echo "something went wrong!"
fi
或使用if测试返回0或1
if check_it_is_a_directory $FILENAME; then
echo "all is ok"
else
echo "something went wrong!"
fi
6、shell中使用函数
set命令可查看所有定义函数,包括已载入shell的所有函数;改动函数需用unset删除函数(非真正删除,仅对与shell或脚本不可利用),改完再重新载入此文件。
7、创建函数文件
创建包容函数的函数文件并载入shell,函数名为functions.main,如下:
#!/bin/bash
#functions.main
#
#findit: this is front end for the basic find command
findit()
{
if [ $# -lt 1 ]; then
echo "usage : findit file"
return 1
fi
find / -name $1 -print
}
8、定位文件
格式 . pathname/filename
将文件载入shell,如
. functions.main(点+空格+文件名(目录名+文件名))
9、检查载入函数
set命令确保函数已载入
set | grep findit可查看到载入函数findit
10、shell函数修改、删除、集中
删除函数使其对shell不可利用
unset function_name
set命令检查确认
编辑函数functions.main,加入for循环以便脚本可从命令行中读取多个参数
#!/bin/bash
#functions.main
#
#findit: this is front end for the basic find command
findit()
{
if [ $# -lt 1 ]; then
echo "usage : findit file"
return 1
fi
for loop
do
find / -name $1 -print
done
}
11、脚本中或文件中调用函数
脚本中调用函数:
#!/bin/bash
#function file
is_it_a_directory()
{
_DIRECTORY_NAME=$1
if [ $# -lt 1 ]; then
echo "is_it_a_directory: I need a directory name to check"
return 1
fi
if [ ! -d $_DIRECTORY_NAME ]; then
return 1
else
return 0
fi
}
error_msg()
{
echo -e "\007"
echo $@
echo -e "\007"
return 0
}
echo -n "enter destination directory :"
read DIREC
if is_it_a_directory $DIREC
then :
else
error_msg "$DIREC does not exist...creating it now"
mkdir $DIREC > /dev/null 2>&1
if [ $? != 0 ]
then
error_msg "could not create directory:: check it out!"
exit 1
else :
fi
fi
echo "extracting files..."
从函数文件中调用函数:
将函数is_it_a_directory放入到function.sh函数文件中,如下:
#!/bin/bash
#functions.sh
#main script functions
is_it_a_directory()
{
_DIRECTORY_NAME=$1
if [ $# -lt 1 ]; then
echo "is_it_a_directory: I need a directory name to check"
return 1
fi
if [ ! -d $_DIRECTORY_NAME ]; then
return 1
else
return 0
fi
}
error_msg()
{
echo -e "\007"
echo $@
echo -e "\007"
return 0
}
编写脚本调用该文件中的函数需要文件定位,如: 点+空格+函数文件(目录+函数文件),如以下脚本中的调用:
#!/bin/bash
#direc_check
#source the function file function.sh
#that's a <dot><space><forward slash>
. home/test/script/function/function.sh
echo -n "enter destination directory :"
read DIREC
if is_it_a_directory $DIREC
then :
else
error_msg "$DIREC does not exist...creating it now"
mkdir $DIREC > /dev/null 2>&1
if [ $? != 0 ]
then
error_msg "could not create directory:: check it out!"
exit 1
else :
fi
fi
echo "extracting files..."
12、定位文件不仅用于函数
也包含组成配置文件的全局变量
如,先定义个配置文件backfunc,然后从另个脚本readfuc中通过定位文件调用该配置文件中的参数,如下:
#!/bin/bash
#name:backfunc
_CODE="comet"
_FULLBACKUP="yes"
_LOGFILE="/logs/backup/"
_DEVICE="/dev/rmt/0n"
_INFORM="yes"
_PRINT_STATS="yes"
通过定位文件调用函数的脚本如下:
#!/bin/bash
#readfuc
if [ -r backfunc ]; then
. backfunc
else
echo "`basename $0` cannot locate backfunc file"
fi
echo -n "Enter the code name : "
read CODE
if [ "${CODE}" != "${_CODE}" ]; then
echo "wrong code...exiting...will use defaults"
exit 1
fi
echo "The enviroment config file reports"
echo "full backup required :$_FULLBACKUP"
echo "the logfile is :$_LOGFILE"
echo "the device to backup to is :$_DEVICE"
echo "you are to be informed by mail :$_INFORM"
echo "a statistic report to be printed:$_PRINT_STATS"
13、函数举例
(1) 变量输入字符判断,如下:
#!/bin/bash
#func2
char_name()
{
_LETTERS_ONLY=$1
_LETTER_ONLY=`echo $1 | awk '{if($0~/[^a-zA-Z]/) print "1"}'`
if [ "$_LETTER_ONLY" != "" ]
then
return 1
else
return 0
fi
}
name_error()
{
echo "$@ contain erros, it must cotain only letters"
}
while :
do
echo -n "entry your first name :"
read F_NAME
if char_name $F_NAME
then
break
else
name_error $F_NAME
fi
done
while :
do
echo -n "entry your second name :"
read S_NAME
if char_name $S_NAME
then
break
else
name_error $S_NAME
fi
done
(2) 提示Y或N的处理
#!/bin/bash
#continue_prompt
continue_prompt()
{
_STR=$1
_DEFAULT=$2
if [ $# -lt 1 ]; then
echo "continue_prompt: I need a string to display"
return 1
fi
while :
do
echo -n "$_STR [Y...N] [$_DEFAULT]:"
read _ANS
if [ "$_ANS" = "" ]; then
: ${_ANS:=$_DEFAULT}
case $_ANS in
Y) return 0 ;;
N) return 1 ;;
esac
fi
case $_ANS in
y|Y|Yes|YES) return 0 ;;
n|N|No|NO) return 1 ;;
*) echo "answer either Y or N,default is $_DEFAULT" ;;
esac
echo $_ANS
done
}
然后文件调用函数
#!/bin/bash
. continue_prompt
if continue_prompt "Do your want to delete the var filesystem" "N"; then
echo "Are you nuts!!"
else
echo "Phew! what a good answer"
fi
(3) 通过用户名寻找ID
定义函数文件
#!/bin/bash
#who_is
who_is()
{
if [ $# -lt 1 ]; then
echo "whois : need user id's please"
return 1
fi
for loop
do
_USER_NAME=`grep $loop /etc/passwd | awk -F: '{print $4}'`
if [ "$_USER_NAME" = "" ]; then
echo "whois: sorry cannot find $loop"
else
echo "$loop is $_USER_NAME"
fi
done
}
脚本调用函数
#!/bin/bash
. who_is
echo "`who_is test see oracle`"
(4) 打印出文本文件行数
#!/bin/bash
#numberfile
numberfile()
{
_FILENAME=$1
if [ $# -lt 1 ]; then
echo "need a filename to number"
return 1
fi
loop=1
while read LINE
do
echo "$loop $LINE"
loop=`expr $loop + 1`
done < $_FILENAME
}
调用该函数文件
#!/bin/bash
. numberfile
numberfile ccc
(5) 大小写转换
定义函数文件
#!/bin/bash
str_to_upper()
{
_STR=$1
if [ $# -ne 1 ]; then
echo "need an string to convert"
return 1
fi
echo $@ | tr '[a-z]' '[A-Z]'
}
脚本调用
#!/bin/bash
. str_to_upper
str_to_upper asdfajkjqke
(6) 判断字符串是否为大写
函数文件
#!/bin/bash
#is_upper
is_upper()
{
if [ $# -ne 1 ]; then
echo "is_upper: I need a string to test OK"
return 1
fi
_IS_UPPER=`echo $1|awk '{if($0~/[^A-Z]/) print "1"}'` 换成 _IS_LOWER=`echo $1|awk '{if($0~/[^a-z]/) print "1"}'` 即是检测小写
if [ "$_IS_UPPER" != "" ]
then
return 1
else
return 0
fi
}
调用脚本
#!/bin/bash
. is_upper
echo -n "entry your name:"
read NAME
if is_upper $NAME; then
echo "Great it is upper case!"
else
echo "it's not upper!"
fi
(7) 字符串长度判断
函数文件
#!/bin/bash
#check_length
check_length()
{
_STR=$1
_MAX=$2
if [ $# -ne 2 ]; then
echo "I need string and max length"
return 1
fi
_LENGTH=`echo $1|awk '{print length($1)}'`
if [ "$_LENGTH" -gt "$_MAX" ]; then
return 1
else
return 0
fi
}
脚本调用
#!/bin/bash
. check_length
while :
do
echo -n "Enter your fisrt name :"
read NAME
if check_length $NAME 10
then
break
else
echo "the name field is too long 10 characters max"
fi
done
wc命令的缺点,会将空格部分也做为字符串的长度来计算
(8) MONTHS显示
函数文件
#!/bin/bash
months_test()
{
_MONTHS=$1
if [ $# -ne 1 ]; then
echo "months: I need a number 1 to 12 "
return 1
fi
case $_MONTHS in
1|01|Jan)_FULL="January" ;;
2|02|Feb)_FULL="February" ;;
3|03|Mar)_FULL="March" ;;
4|04|Apr)_FULL="April" ;;
5|05|May)_FULL="May" ;;
6|06|Jun)_FULL="June" ;;
7|07|Jul)_FULL="July" ;;
8|08|Aug)_FULL="August" ;;
9|09|Sep|Sept)_FULL="September" ;;
10|Oct)_FULL="October" ;;
11|Nov)_FULL="November" ;;
12|Dec)_FULL="December" ;;
*) echo "months: Unknown month"
return 1
;;
esac
echo $_FULL
}
脚本调用
#!/bin/bash
. months_test
MY_MONTHS=`months_test 02`
echo "the report for Month and $MY_MONTHS"
(9) chop函数,截取部分字符串
函数文件
#!/bin/bash
chop()
{
_STR=$1
_CHOP=$2
CHOP=`expr $_CHOP + 1`
if [ $# -ne 2 ]; then
echo "need a string and an character to chop"
return 1
fi
_LENGTH=`echo $_STR|awk '{print length($0)}'`
if [ "$_LENGTH" -lt "$_CHOP" ]; then
echo "need more characters than there are in the string"
return 1
fi
echo $_STR|awk '{print substr($1,'$CHOP')}'
}
脚本调用
#!/bin/bash
. chop
CHOPED=`chop "1234567890" 5`
echo $CHOPED
相关文章推荐
- SHELL函数实现相对路径转化为绝对路径
- shell函数返回字符串的方法
- shell函数的参数与返回值的例子
- Shell函数学习与整理
- shell函数返回字符串
- 【Shell脚本学习22】Shell 函数:Shell函数返回值、删除函数、在终端调用函数
- 4、Shell函数,Shell数组,变量替换
- Shell函数:Shell函数返回值、删除函数、在终端调用函数
- shell函数
- shell特殊变量\shell函数特殊变量
- shell函数
- Bash脚本编程(四)之Shell函数
- Shell函数返回值
- shell函数传递带空格的参数
- Shell函数与数组
- Shell函数返回值、删除函数、在终端调用函数
- 【Shell脚本学习23】Shell函数参数
- Shell函数:Shell函数返回值、删除函数、在终端调用函数
- Linux Shell系列教程之(十五) Shell函数简介
- Linux环境下svn回滚单个文件的shell函数