shell函数

本文详细介绍Bash脚本中的函数定义与使用方法,包括基本格式、参数传递、返回值处理及函数文件创建等核心内容,并提供多个实用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值