Shell Script 用户输入

命令行参数

bash shell会将一些称为位置参数的特殊变量分配给输入到命令行中的所有参数。这也包括shell所执行的脚本名称。位置参数变量是标准的数字:$0是程序名,$1是第一个参数,$2是第二个参数,依次类推,直到第九个参数$9。

$ cat test2.sh
#!/bin/bash
#
total=$[ $1 * $2 ]
echo The first parameter is $1.
echo The second parameter is $2.
echo The total value is $total.
$ ./test2.sh 2 5
The first parameter is 2.
The second parameter is 5.
The total value is 10.
$

可以用$0参数获取shell在命令行启动的脚本名。当传给$0变量的实际字符串不仅仅是脚本名,而是完整的脚本路径时,
变量$0就会使用整个路径。basename命令会返回不包含路径的脚本名。name=$(basename $0)

$ cat test5.sh
#!/bin/bash
echo The zero parameter is set to: $0
$
$ bash test5.sh
The zero parameter is set to: test5.sh

可以使用-n测试来检查命令行参数$1中是否有数据(此处的“$1”双引号是必须的)。对于使用多个命令行参数的脚本来说,这有点麻烦。特殊变量$#含有脚本运行时携带的命令行参数的个数

$ cat test7.sh
#!/bin/bash
if [ -n "$1" ]
then
    echo Hello $1, glad to meet you.
else
    echo "Sorry, you did not identify yourself. "
fi
$ cat test8.sh
#!/bin/bash
echo There were $# parameters supplied.
$ ./test8.sh
There were 0 parameters supplied.
$ ./test8.sh 1 2 3 4 5
There were 5 parameters supplied.
$ ./test8.sh "Rich Blum"
There were 1 parameters supplied.
  • 抓取所有输入参数

$*$@变量可以用来轻松访问所有的参数。

  • $*变量会将命令行上提供的所有参数当作一个单词保存。这个单词包含了命令行中出现的每一个参数值。基本上$*变量会将这些参数视为一个整体,而不是多个个体。
  • $@变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。这样你就能够遍历所有的参数值,得到每个参数。这通常通过for命令完成。
for param in "$*"
do
    echo "\$* Parameter #$count = $param"
    count=$[ $count + 1 ]
done
for param in "$@"
do
    echo "\$@ Parameter #$count = $param"
    count=$[ $count + 1 ]
done
$ ./test12.sh rich barbara katie jessica
$* Parameter #1 = rich barbara katie jessica
$@ Parameter #1 = rich
$@ Parameter #2 = barbara
$@ Parameter #3 = katie
$@ Parameter #4 = jessica
  • 移动输入参数

在使用shift命令时,默认情况下它会将每个参数变量向左移动一个位置(也可以一次性移动多个位置)。所以,变量$3的值会移到$2中,变量$2的值会移到$1中,而变量$1的值则会被删除(注意,变量$0的值,也就是程序名,不会改变)。如果某个参数被移出,它的值就被丢弃了,无法再恢复

这是遍历命令行参数的另一个好方法,尤其是在你不知道到底有多少参数时。你可以只操作第一个参数,移动参数,然后继续操作第一个参数。

count=1
while [ -n "$1" ]
do
    echo "Parameter #$count = $1"
    count=$[ $count + 1 ]
    shift
done
$ ./test13.sh rich barbara katie jessica
Parameter #1 = rich
Parameter #2 = barbara
Parameter #3 = katie
Parameter #4 = jessica
$

命令行选项

一些bash命令同时提供了参数和选项的。选项是跟在单破折线后面的单个字母,它能改变命令的行为。

  • 获得选项

在提取每个单独参数时,用shift+case语句判断某个参数是否为选项。

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
$ ./test15.sh -a -b -c -d
Found the -a option
Found the -b option
Found the -c option
-d is not an option
$

在shell脚本中同时使用选项和参数的情况,shell会用双破折线(--)来表明选项列表结束,剩下当作命令行参数。

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

有些选项会带上一个额外的参数值。当命令行选项要求额外的参数时,脚本必须能检测到并正确处理。

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
  • getopt 命令

getopt命令可以接受一系列任意形式的命令行选项和参数,并自动将它们转换成适当的格式

getopt optstring parameters

在optstring中列出你要在脚本中用到的每个命令行选项字母。然后,在每个需要参数值的选项字母后加一个冒号。getopt命令会基于你定义的optstring解析提供的参数。自动将-cd选项分成两个单独的选项

$ getopt ab:cd -a -b test1 -cd test2 test3
-a -b test1 -c -d -- test2 test3
$

脚本中使用getopt来格式化脚本所携带的任何命令行选项或参数。set命令的选项之一是双破折线(--),它会将命令行参数替换成set命令的命令行值。然后将原始脚本的命令行参数传给getopt命令,之后再将getopt命令的输出传给set命令,用getopt格式化后的命令行参数来替换原始的命令行参数,

set -- $(getopt -q ab:cd "$@")
#!/bin/bash
set -- $(getopt -q ab:cd "$@")

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
$ ./test18.sh -ac
Found the -a option
Found the -c option
$
  • 将选项标准化 

有些字母选项在Linux世界里已经拥有了某种程度的标准含义。如果你能在shell脚本中支持这些选项,脚本看起来能更友好一些。

标准命令选项
-a 显示所有对象
-c 生成一个计数
-d 指定一个目录
-e 扩展一个对象
-f 指定读入数据的文件
-h 显示命令的帮助信息
-i 忽略文本大小写
-l 产生输出的长格式版本
-n 批处理
-o 输出重定向
-r 递归处理目录和文件

用户输入

read命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read命令会将数据放进一个变量。echo命令使用了-n选项。该选项不会在字符串末尾输出换行符,允许脚本用户紧跟其后输入数据

#!/bin/bash
echo -n "Enter your name: "
read name
echo "Hello $name, welcome to my program. "
$ ./test21.sh
Enter your name: Rich Blum
Hello Rich Blum, welcome to my program.
$

read命令包含了-p选项,允许你直接在read命令行指定提示符。

read -p "Please enter your age: " age

read命令会将提示符后输入的所有数据分配给单个变量,要么你就指定多个变量。输入的每个数据值都会分配给变量列表中的下一个变量。如果变量数量不够,剩下的数据就全部分配给最后一个变量。

read -p "Enter your name: " first last

也可以在read命令行中不指定变量。如果是这样,read命令会将它收到的任何数据都放进特殊环境变量REPLY中。

  • 超时提醒

可以用-t选项来指定一个计时器。-t选项指定了read命令等待输入的秒数。当计时器过期后,read命令会返回一个非零退出状态码。

if read -t 5 -p "Please enter your name: " name

另外可以让read命令来统计输入的字符数,当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量。本例中将-n选项和值1一起使用,告诉read命令在接受单个字符后退出,无需按回车键。

read -n1 -p "Do you want to continue [Y/N]? " answer
  • 隐藏输入

不想输入数据显示。-s选项可以避免在read命令中输入的数据出现在显示器上(实际上,数据会被显示,只是read命令会将文本颜色设成跟背景色一样)

read -s -p "Enter your password: " pass
  • 从文件中读取

可以用read命令来读取Linux系统上文件里保存的数据。每次调用read命令,它都会从文件中读取一行文本。当文件中再没有内容时,read命令会退出并返回非零退出状态码。

其中最难的部分是将文件中的数据传给read命令。最常见的方法是对文件使用cat命令,将结果通过管道直接传给含有read命令的while命令

#!/bin/bash
count=1
cat test | while read line
do
echo "Line $count: $line"
count=$[ $count + 1]
done
echo "Finished processing the file"
$

猜你喜欢

转载自blog.csdn.net/linshuo1994/article/details/84138493
今日推荐