14.1 命令行参数

14.1.1 读取参数

$0~$9 :

  • 超过9的使用 ${10} 方式
  1. #!/bin/bash
  2. # using one command line parameter
  3. #
  4. factorial=1
  5. for (( number = 1; number <= $1; number++ ))
  6. do
  7. factorial=$[ $factorial * $number ]
  8. done
  9. echo The factorial of $1 is $factorial

14.1.2 读取脚本名

basename:

#!/bin/bash
# Using basename with the $0 parameter
#
name=$(basename $0)
echo
echo The script name is: $name
#

14.1.3 测试参数

#!/bin/bash
# testing parameters before use
#
if [ -n "$1" ]
then
    echo Hello $1, glad to meet you.
else
    echo "Sorry, you did not identify yourself."
fi

14.2 特殊参数变量

14.2.1 参数统计

$# : 参数数量

  • 不包括 $0
#!/bin/bash
# getting the number of parameters
#
echo There were $# parameters supplied.

${!#} : 最后一个参数

#!/bin/bash
# Grabbing the last parameter
#
params=$#
echo
echo The last parameter is $params
echo The last parameter is ${!#}
echo
#

14.2.2 抓取所有的数据

$*$@ 都存储了所有参数:

  • $* : 将所有参数当作一个单词
  • $@ : 多个独立的单词
#!/bin/bash
# testing $* and $@
#
echo
count=1
#
for param in "$*"
do
    echo "\$* Parameter #$count = $param"
    count=$[ $count + 1 ]
done
#
echo
count=1
#
for param in "$@"
do
    echo "\$@ Parameter #$count = $param"
    count=$[ $count + 1 ]
done

14.3 移动变量

shift: 向左移动参数

  • $1 的值向左移动后, 该值将被删除
  • $0 的值不变
  • 默认情况下移动移动一个位置
  • 被删除的值无法再恢复
#!/bin/bash
# demonstrating the shift command
echo
count=1
while [ -n "$1" ]
do
    echo "Parameter #$count = $1"
    count=$[ $count + 1 ]
    shift
done

移动多个位置:

shift n

14.4 处理选项

14.4.1 查找选项

1. 处理简单选项

#!/bin/bash
# extracting command line options as parameters
#
echo
while [ -n "$1" ]
do
    case "$1" in
        -a) echo "Found the -a option" ;;
        -b) echo "Found the -b option" ;;
        -c) echo "Found the -c option" ;;
         *) echo "$1 is not an option" ;;
    esac
    shift
done

2. 分离参数和选项

-- : shell会用双破折线来表明选项列表结束

#!/bin/bash
# extracting options and parameters
echo
while [ -n "$1" ]
do
    case "$1" in
        -a) echo "Found the -a option" ;;
        -b) echo "Found the -b option" ;;
        -c) echo "Found the -c option" ;;
        --) shift # 移除--
            break ;;
         *) echo "$1 is not an option" ;;
    esac
    shift
done
#
count=1
for param in $@
do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done

3. 处理带值的选项

#!/bin/bash
# extracting command line options and values
echo
while [ -n "$1" ]
do
    case "$1" in
        -a) echo "Found the -a option" ;;
        -b) param="$2"
            echo "Found the -b option, with parameter value $param"
            shift ;;
        -c) echo "Found the -c option" ;;
        --) shift
            break ;;
         *) echo "$1 is not an option" ;;
    esac
    shift
done
#
count=1
for param in "$@"
do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done

14.4.2 使用 getopt 命令

  • 更高级的版本: getopts

1. 命令的格式

getopt optstring parameters

使用:

  • 定义了 a, b, c, d 选项
  • b 选项需要参数
$ getopt ab:cd -a -b test1 -cd test2 test3
 -a -b test1 -c -d -- test2 test3

忽略不存在的选项提示:

  • -q
$ getopt -q ab:cd -a -b test1 -cde test2 test3
 -a -b 'test1' -c -d -- 'test2' 'test3'

2. 在脚本中使用 getopt

  • set 命令的选项之一是双破折线 ( — ), 它会将命令行参数替换成 set 命令的命令行值。
#!/bin/bash
# Extracting command line options & values with getopt
#
set -- $(getopt -q ab:cd "$@")
#
echo
while [ -n "$1" ]
do
    case "$1" in
        -a) echo "Found the -a option" ;;
        -b) param="$2"
            echo "Found the -b option, with parameter value $param"
            shift ;;
        -c) echo "Found the -c option" ;;
        --) shift
            break ;;
         *) echo "$1 is not an option" ;;
    esac
    shift
done
#
count=1
for param in "$@"
do
    echo "Parameter #$count: $param"
    count=$[ $count + 1 ]
done
#
  • getopt 的问题是不能处理带有空格的参数 (无法识别为一个单词)

14.4.3 使用更高级的 getopts

  • 内建于 bash shell
  • 使用 OPTARG, OPTIND 环境变量
  • 要去掉错误消息: 在 optstring 之前加冒号

格式:

getopts optstring variable

使用:

#!/bin/bash
# simple demonstration of the getopts command
#
echo
while getopts :ab:c opt
do
    case "$opt" in
        a) echo "Found the -a option" ;;
        b) echo "Found the -b option, with value $OPTARG" ;;
        c) echo "Found the -c option" ;;
        *) echo "Unknown option: $opt" ;;
    esac
done
  • 参数可以包含空格
  • 选项和参数可以挨着, 而不用空格分隔
  • 对未定义的选择输出为 ?
#!/bin/bash
# Processing options & parameters with getopts
#
echo
while getopts :ab:c opt
do
    case "$opt" in
        a) echo "Found the -a option" ;;
        b) echo "Found the -b option, with value $OPTARG" ;;
        c) echo "Found the -c option" ;;
        *) echo "Unknown option: $opt" ;;
    esac
done
#
shift $[ $OPTIND - 1 ]
#
echo
count=1
for param in "$@"
do
    echo "Parameter $count: $param"
    count=$[ $count + 1 ]
done

14.5 将选项标准化

常用选项含义:

image.png

14.6 获得用户输入

read 命令

14.6.1 基本的读取

  • -p
#!/bin/bash
# testing the read -p option
#
read -p "Please enter your age: " age
days=$[ $age * 365 ]
echo "That makes you over $days days old! "
#
  • 可以使用多个变量
read -p "Enter your name: " first last
  • 可以不指定变量, 数据会放到 REPLY 环境变量中, 之后可以引用

14.6.2 超时

  • -t , 单位: 秒
#!/bin/bash
# timing the data entry
#
if read -t 5 -p "Please enter your name: " name
then
    echo "Hello $name, welcome to my script"
else
    echo
    echo "Sorry, too slow! "
fi
  • -n : 限制输入字符数. 无需按回车
read -n1 -p "xxx" var

14.6.3 隐藏方式读取

  • -s : 将输入设置成背景颜色, 从而隐藏
read -s -p "xxx" var

14.6.4 从文件中读取

  • 每次读取文件中的一行
  • 没有内容了返回非0退出状态码
#!/bin/bash
# reading data from a file
#
count=1
cat test | while read line
do
    echo "Line $count: $line"
    count=$[ $count + 1 ]
done
echo "Finished processing the file"

14.7 小结