shell编程lesson09

位置参数

        之前一直没有涉及程序接收和处理命令行选项及实参的能力,本节将介绍程序访问命令行内容的shell功能

访问命令行

        shell提供了一组名为位置参数的变量,用于存储命令行中的关键字,这些变量分别命名0~9,可以通过以下方式访问这些变量

#!/bin/bash

# posit-param:script to view command line parameters

echo "
\$0 = $0
\$1 = $1
\$2 = $2
\$3 = $3
\$4 = $4
\$5 = $5
\$6 = $6
\$7 = $7
\$8 = $8
\$9 = $9
"

在没有任何命令行实参的情形下执行此脚本,运行结果如下

$0 = a.sh
$1 = 
$2 = 
$3 = 
$4 = 
$5 = 
$6 = 
$7 = 
$8 = 
$9 = 

可以看到,即便没有任何的命令行实参,变量$0总是会存储所执行程序所在的文件名

!!!使用参数扩展技术,用户实际可以获取多于9个的位置参数,为标明一个大于9的数字,需要将数字用大括号括起来,例如${10}、${56}、${256}

确定实参的数目

shell还提供了变量 $# 以给出命令行参数的个数。

#!/bin/bash

# posit-param:script to view command line parameters

echo "
Number of arguments:$#
\$0 = $0
\$1 = $1
\$2 = $2
\$3 = $3
\$4 = $4
\$5 = $5
\$6 = $6
\$7 = $7
\$8 = $8
\$9 = $9
\$10 = ${10}
"

($0 :表示执行脚本名称;$# :表示命令行参数个数)

shift——处理大量的实参

#!/bin/bash

# posit-param2:script to display all arguments

count=1

while [[ $# -gt 0 ]];do
        echo "Argument $count: $1"
        count=$((count+1))
        shift
done

        shift提供了一种机制,每次执行shift命令后,所有的参数值均“下移一位”。即变量$2的值会赋给变量$1,而$3的值则会赋给变量$2,以此类推,全部“下移一位”,并且变量$#的值同时减1。

        通过shift命令,我们只需要处理一个参数即可,即$1。

        以上脚本,创建了一个循环,只要还存在1个实参,循环就不停止。首先输出当前的实参,其次,每次循环迭代一次,就将变量count值加1,代表处理过的实参数目。最后,执行shift命令使得$1载入下一个实参的值。

一个简单的应用程序

#!/bin/bash

# file_info:simple file information program

PROGNAME=$(basename $0)
while [[ $# -gt 0 ]];do
if [[ -e $1 ]];then
        echo -e "\nFile Type:"
        file $1
        echo -e "\nFile Status:"
        stat $1
else
        echo "$PROGNAME: usage:$PROGNAME file" >&2
        exit 1
fi
shift
done

列出指令路径下实参(路径下的各类文件)的文件类型(file命令)和文件状态(stat命令)。

在shell函数中使用位置参数

        如同位置参数可以向脚本传递实参一样,位置参数也可以用于shell函数实参的传递

file_info(){
    # file_info:functiono to display file information
    if [[ -e $1 ]];then
        echo -e "\nFile Type:"
        file $1
        echo -e "\nFile Status:"
        stat $1
    else
        echo "$FUNCNAME: usage: $FUNCNAME file" >&2
        return 1
    fi
}

        函数的返回状态用return,如果不是函数则用exit命令。  tips

        我们不仅可以在普通脚本中传递位置参数给函数,也可以在.bashrc文件中维护使用位置参数的函数。

        需要注意的是,PROGNAME变量被换成了名为FUNCNAME的shell变量。shell会自动更新FUNCNAME以追踪当前执行的shell函数。

        $0变量表示的是执行脚本的脚本文件名称;$FUNCNAME变量用于函数中,表示的是所在函数的名称。注意区别。

处理多个位置参数

        有时候我们会把所有位置参数当做一个整体来处理。

shell为这项功能提供了两种特殊的参数。两种参数都能扩展为一个完整的位置参数列,但是又有着微妙的区别。

参数 描述
$* 可扩展为从1开始的位置参数列。当包括在双引号内时,扩展为双引号引用的由全部位置参数构成的字符串,每个位置参数以IFS shell变量的第一个字符(默认情况下为空格)间隔开
$@ 可扩展为从1开始的位置参数列。当包含在双引号内时,将每个位置参数扩展为双引号引用的单独单词
#!/bin/bash

# posit-params3:script to demonstrate $* and $@

print_params(){
        echo "\$1 = $1"
        echo "\$2 = $2"
        echo "\$3 = $3"
        echo "\$4 = $4"
}

pass_params(){
        echo -e "\n" '$* :';print_params $*
        echo -e "\n" '"$*" :';print_params "$*"
        echo -e "\n" '$@ :';print_params $@
        echo -e "\n" '"$@" :';print_params "$@"
}

pass_params "word" "words with spaces"

执行结果


 $* :
$1 = word
$2 = words
$3 = with
$4 = spaces

 "$*" :
$1 = word words with spaces
$2 = 
$3 = 
$4 = 

 $@ :
$1 = word
$2 = words
$3 = with
$4 = spaces

 "$@" :
$1 = word
$2 = words with spaces
$3 = 
$4 = 

"$*" 和 "$@" 都产生了包含4个单词的结果。"$*"产生的是只包含一条字符串的结果,即word words with spaces。"$@"产生的则是包含了两条字符串的结果,即word和words with spaces。

        因为"$@"保持了每个位置参数的完整性,没有破坏位置参数的结构,所以"$@"是大多数情况下的使用格式!

更完整的应用程序

        在位置参数的帮助下,用户可以写出功能性更强的脚本。通常,对于重复性的任务,位置参数使得用户可以写出很有帮助的shell函数,并放置在用户的.bashrc文件中。

        回到系统信息报告生成器脚本,如下

#!/bin/bash

# sys_info_page: program to output a system information page

PROGNAME=$(basename $0)
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME=$(date +"%x %r %Z")
TIME_STAMP="Generated $CURRENT_TIME ,by $USER"

report_uptime () {
        cat <<- _EOF_
                

System Uptime

$(uptime)
_EOF_ return } report_disk_space () { cat <<- _EOF_

Disk Space Utilization

$(df -h)
_EOF_ return } report_home_space () { if [[ $(id -u) -eq 0 ]];then cat <<- _EOF_

Home Space Utilization(All Users)

$(du -sh /home/*)
_EOF_ else cat <<- _EOF_

Home Space Utilization ($USER)

$(du -sh $HOME)
_EOF_ fi return } usage () { echo "$PROGNAME: usage: $PROGNAME [-f file| -i ]" return } write_html_page () { cat <<- _EOF_ $TITLE

$TITLE

$TIME_STAMP

$(report_uptime) $(report_disk_space) $(report_home_space) _EOF_ return } # process command line option interactive= filename= while [[ -n $1 ]];do case $1 in -f | --file) shift filename=$1 ;; -i | --interactive) interactive=1 ;; -h | --help) usage exit ;; *) usage >&2 exit 1 ;; esac shift done # interactive mode if [[ -n $interactive ]];then while true;do read -p "Enter name of output file: " filename if [[ -e $filename ]];then read -p "'$filename' exists. Overwrite? [y/n/q] > " case $REPLY in Y|y) break ;; Q|q) echo "Program terminated." exit ;; *) continue ;; esac elif [[ -z $filename ]];then continue else break fi done fi # output html page if [[ -n $filename ]];then if touch $filename && [[ -f $filename ]];then write_html_page > $filename else echo "$PROGNAME:Cannot write file '$filename'" >&2 exit 1 fi else write_html_page fi

需要多看以上脚本,理解与学习其编写脚本的设计思想。

你可能感兴趣的:(linux,linux,bash,运维,ssh,服务器)