Bash编程(5) Shell方法

shell的方法在相同的进程内执行,与调用它的脚本一致。对于方法来说,脚本中的所有变量均可见,且不需要执行export。方法中可以创建局部变量,且不影响正在调用的脚本。

 1. 定义语法

(1) KornShell中的定义格式为:function name <复合命令>

(2) Bourne shell中的定义格式为: name() <复合命令>

(3) bash允许的格式:function name() <复合命令>

一个参数设置方法的返回码,若没有参数,方法的退出码默认为执行的最后一个命令执行结果。

 

local为shell中的内置命令,可用于限制方法(以及其子方法)中变量的作用域,但父进程中的变量不会改变。当参数扩展时,使用IFS而非空格将会导致分词。Bash4.0中, local和declare存在一个选项 -A,用于声明关联数组。

例:判断ip是否有效

## 检测Ip是否有效
isvalidip(){
    case $1 in
    "" | *[!0-9.]* | *[!0-9]) return 1 ;;  ## 空值、非法字符、不以数字结尾,均不符合Ip
    esac

    ## 将IFS设置为点号,但仅限于该方法中
    local IFS=.

    ## 将Ip设为位置参数,分词之后,每个元素变成了参数
    set -- $1
    
    ## 必须有4个参数,每个元素必须小于256,参数为空时,默认为666
    [ $# -eq 4 ] &&
    [ ${1:-666}  -le 255 ] && 
    [ ${2:-666}  -le 255 ] &&
    [ ${3:-666}  -le 255 ] &&
    [ ${4:-666}  -le 255 ] &&
}

 使用source命令使脚本中的方法在当前shell中有效:. isvalidip

$ for ip in 127.0.0.1 168.260.0.234 123.100.34.32 204.255.122.150
> do
>     if isvalidip "$ip"
>     then
>         printf "%15s: valid\n" "$ip"
>     else
>         printf "%15s: invalid\n" "$ip"
>     fi
> done

127.0.0.1: valid
168.260.0.234: invalid
123.100.34.32: valid
204.255.122.150: valid

 2. 复合命令

复合命令可以是一组封装在( ... )或{ ... }中的命令,封装在(( ... ))或[[ ... ]]中的表达式,或者shell的关键词块(case, for, while, select, until)。

例:检查有效整型

valint()  #@ USAGE: valint INTEGER
    case ${1#-} in  ## 接收负数
        *[!0-9]*) echo false;; ## 包含非数字字符
        *) echo true;;
    esac

    若方法的主体由引号包含,则它将在子shell中执行,并且执行期间产生的变化在退出时不再有效。

$ funky() (nam=nobody; echo "name = $name")
name=Rempelstilskin
$ funky
name = nobody
$ echo "name = $name"
name = Rempelstilskin

3. 获取结果

1) 设置不同的退出码

例:检验整型是否在特定范围

rangecheck()  #@ USAGE: rangecheck int [low  [high]]
    if [ "$1" -lt ${2:-10} ];then ## 数值太小返回1,若无第二个参数,默认为10
        return 1
    elif [ "$1" -gt ${3:-20} ];then ## 数据太大返回0,若无第三个参数,默认为20
        return 2
    else
        return 0
    fi

2) 打印结果

例:打印环境变量信息

uinfo()  #@ USAGE: uinfo [file]
{
    printf "%12s: %s\n" \
        USER "${USER:-No value assigned }" \
        PWD "${PWD:-No value assigned}" \
        COLUMNS "${COLUMNS:-No value assigned}" \
        LINES "${LINES:-No value assigned}" \
        SHELL "${SHELL:-No value assigned}" \
        HOME "${HOME:-No value assigned}" \
        TERM "${TERM:-No value assigned}"
} > ${1:-/dev/fd/1}

 3) 结果保存在多个变量中

例:3个整数排序

_max3()  #@ 对3个整数排序,并且分别保存在$_MAX3,$_MID3及$_MIN3中
{
    [ $# -ne 3 ] && return 5
    [ $1 -gt $2 ] && { set -- $2 $1 $3; }
    [ $2 -gt $3 ] && { set -- $1 $3 $2; }
    [ $1 -gt $2 ] && { set -- $2 $1 $3; }
    _MAX3=$3
    _MID3=$2
    _MIN3=$1
    printf "%d\t%d\t%d\n" $_MAX3 $_MID3 $_MIN3
}

max3() #@ 对3个整数排序并保存在array中
{
declare -n _max3=${4:-_MAX3}  #@ 当命令行未提供变量名,则默认使用_MAX3
(( $# < 3 )) && return 4
(( $1 > $2 )) && set -- "$2" "$1" "$3"
(( $2 > $3 )) && set -- "$1" "$3" "$2"
(( $1 > $2 )) && set -- "$2" "$1" "$3"
_max3=( "$3" "$2" "$1" )
}

 4. 示例脚本 

##
##  设置默认
##
prompt=" ==> "
template='<!DOCTYPY html>
<html lang="en">
  <head>
    <meta charset=utf-8>
    <title>%s</title>
    <link href=%s" rel="stylesheet">
  </head>
  <body>
    <h1>%s</h1>
    <div id=main></div>
  </body>
</html>
'

## 
##  定义shell函数
##
die(){  #@ 描述:打印错误信息,并且以ERROR退出
    error=$1
    shift
    [ -n "$*" ] && printf "%s\n" "$*" >&2
    exit "$error"
}

usage(){  #@ 打印脚本使用用途
    printf "USAGE: %s HTMLFILE\n" "$progname"
}

version(){
    printf "%s version %s: " "$progname" "${version:-1}"
}

bashversion=${BASH_VERSION%%.*}
if [ ${bashversion:-0} -ge 4 ];then
    ## bash4.x 的read有-i选项,用于提供一个初始值(如下的$3)
    readline(){
        read -ep "${2:-"$prompt"}" -i "$3" "$1"
    }
elif [ ${BASHVERSION:-0} -ge 2 ];then
    readline(){
        history -s "$3"
        printf "Press up arror to edit default value: '%s'\n" "${2:-none}"
        read -ep "${2:-"$prompt"}" "$1"
    }
else
    readline(){
        printf "Press enter for default of '%s'\n" "$3"
        printf "%s " "${2:-"$prompt"}"
        read
        eval "$1=\${REPLY:-"$3"}"
    }
fi

if [ $# -ne 1 ];then
    usage
    exit 1
fi

filename=$1

readline title "Page title: "
readline h1 "Main headline: " "$title"
readline css "Style sheet file: " "${filename%.*}.css"

printf "$template" "$title" "$css" "$h1" > "$filename" 
执行示例结果: 
$ bash test.sh test
Page title: hello
Main headline: hello
Style sheet file: test.css
$ cat test
<!DOCTYPY html>
<html lang="en">
  <head>
    <meta charset=utf-8>
    <title>hello</title>
    <link href=test.css" rel="stylesheet">
  </head>
  <body>
    <h1>hello</h1>
    <div id=main></div>
  </body>
</html>

 

posted @ 2019-02-12 21:47  mengrennwpu  阅读(455)  评论(0编辑  收藏  举报