Appearance
处理用户输入
bash shell提供了一系列的方法从用户处获取参数
命令行参数
最基本的方法, 在使用命令行的时候传递参数
读取参数
bash shell会将一些称为位置参数的特殊变量分配给命令行中的所有参数, 包括shell的脚本名
位置参数的变量名是标准的数字: $0 程序名, $1 第一个参数, $9: 最后一个参数
bash
1 #!/bin/bash
2 factorial=1
3 for ((number=1;number<=$1;number++))
4 do
5 factorial=$[$factorial*$number]
6 done
7 echo The factorial of $1 is $factorial
在输入的是字符串的时候, 如果一个值之间有空格, 要用引号引起来
如果脚本的参数不止九个, 可以使用大括号把数字引起来
${10}
读取脚本名
读取脚本名的时候会把路径一同传递最为第一个参数
有一个命令会返回正确的程序
bash
basename
bash
1 #!/bin/bash
2
3 name=$(basename $0)
4 echo
5 echo The name is $name
- 处理多个文件名的文件
bash
1 #!/bin/bash
2
3 name=$(basename $0)
4 if [ $name == "addem" ]
5 then
6 total=$[ $1 + $2 ]
7 elif [ $name == "multem" ]
8 then
9 total=$[ $1 * $2 ]
10 fi
11 echo
12 echo The calculated value is $total
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ ln -s test4.sh addem
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ ln -s test4.sh multem
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ addem 1 2
The calculated value is 3
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ multem 3 4
The calculated value is 12
测试参数
在使用参数之前应该测试参数是不是为空
bash
1 #!/bin/bash
2
3 if [ -n "$1" ] # 字符串非空
4 then
5 echo Hello $1, glod to meet you
6 else
7 echo "Sorry, you did not identify yourself"
8 fi
特殊参数变量
bash shell 会有一些特殊的参数记录命令行的参数
参数统计
可以统计一下输入了多少个参数, 用$#
bash
1 #!/bin/bash
2 echo There were $# parameter supplied
参数的计数不算文件名
bash
1 #!/bin/bash
2
3 if [ $# -ne 2 ]
4 then
5 echo
6 echo Usage: test9.sh a b
7 echo
8 else
9 total=$[ $1+$2 ]
10 echo
11 echo The total is $total
12 echo
13 fi
- 获取最后一个参数, 在{}中不能使用$, 要把他换成!
bash
${!#}
bash
1 #!/bin/bash
2 params=$#
3 echo
4 echo The last parameter is $params # 打印参数的数量
5 echo The last parameter is ${!#} # 打印最后一个参数
6 echo
抓取所有的数据
使用#@ 和 #* 可以轻松的访问所有的数据, 在单个变量中存储所有的命令行参数
- $*会把所有的参数当做一个存储, 视为一个整体
- $@会把所有的参数当做一个字符串的多个独立的单词, 这样你就可以遍历所有参数
bash
1 #!/bin/bash
2 echo
3 echo "Using the \$* method: $*"
4 echo "Using the \$@ method: $@"
5 echo
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test9.sh 123 321 432 234 jjj
Using the $* method: 123 321 432 234 jjj
Using the $@ method: 123 321 432 234 jjj
bash
1 #!/bin/bash
2
3 echo
4 cout=1
5 for param in "$*"
6 do
7 echo "\$* parameter #$cout = $param"
8 cout=$[ $cout+1 ]
9 done
10 echo
11 for param in "$@"
12 do
13 echo "\$@ Parameter #$count = $param"
14 count=$[ $count + 1 ]
15 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test10.sh 123 321 234 432 "New Year"
$* parameter #1 = 123 321 234 432 New Year
$@ Parameter # = 123
$@ Parameter #1 = 321
$@ Parameter #2 = 234
$@ Parameter #3 = 432
$@ Parameter #4 = New Year
移动变量
shift命令能够用来操作命令行参数。
默认情况下它会将每个参数变量向左移动一个位置。所以,变量$3的值会移到$2中,变量$2的值会移到$1中,而变量$1的值则会被删除(注意,变量$0的值,也就是程序名,不会改变)
当不知道有多少个参数的时候, 可以移位然后只是用第一个参数
bash
1 #!/bin/bash
2 echo
3 count=1
4 while [ -n "$1" ]
5 do
6 echo "Parameter #$count = $1"
7 count=$[ $count + 1 ]
8 shift
9 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test11.sh 123 321 "Hello world"
Parameter #1 = 123
Parameter #2 = 321
Parameter #3 = Hello world
移出的参数被丢弃, 无法再次使用
可以用数字指明移动的位置
bash
1 #!/bin/bash
2
3 echo
4 echo "The original parameter: $*"
5 shift 2
6 echo "Here the new : $*"
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test12.sh 123 321 234 432
The original parameter: 123 321 234 432
Here the new : 234 432
处理选型
查找选项
可以像处理命令行参数一样处理命令行选项
处理简单选项
bash
1 #!/bin/bash
2 echo
3 while [ -n "$1" ]
4 do
5 case "$1" in
6 -a) echo "Find the -a option";;
7 -b) echo "Find the -b option";;
8 -c) echo "Find the -c option";;
9 -d) echo "Find the -d option";;
10 *) echo "$1 is not an option";;
11 esac
12 shift
13 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test13.sh 123 321 -a -b -c
123 is not an option
321 is not an option
Find the -a option
Find the -b option
Find the -c option
分离参数和选项
在shell脚本中同时使用选项和参数的情况。Linux中处理这个问题的标准方式是用特殊字符来将二者分开,该字符会告诉脚本何时选项结束以及普通参数何时开始
特殊字符是双破折线(--)。在双破折线之后,脚本就可以放心地将剩下的命令行参数当作参数,而不是选项来处理了
在case中对参数进行判断, 如果参数是--就退出循环
处理带值的选项
在case之中对参数进行处理, 并用shift进行移位
使用getopt
命令
在处理命令行选项和参数的时候非常的方便
命令的格式
getopt
命令可以接受一系列各种形式的命令行选项以及参数
bash
getopt optstring parameters
optstring
定义了命令行有效的选项字母, 还定义了哪些选项字母需要参数值
在optstring
中列出你要在脚本中用到的每个命令行选项字母。然后,在每个需要参数值的选项字母后加一个冒号。getopt
命令会基于你定义的optstring
解析提供的参数
有一个高级的版本叫做
optstrings
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ getopt ab:cd -a -b test1 -cd test1 test2
-a -b test1 -c -d -- test1 test2
输入了不存在的参数, 就会报错, 可以使用-q参数进行屏蔽
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ getopt ab:cd -a -b test1 -cd test1 test2 -e
getopt: 不适用的选项 -- e
-a -b test1 -c -d -- test1 test2
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ getopt -q ab:cd -a -b test1 -cd test1 test2 -e
-a -b 'test1' -c -d -- 'test1' 'test2'
命令选项必须出现在
optdtrings
之前
在脚本中使用getopt
使用getopt
处理后的参数替换原来的参数, 使用set命令
bash
set -- $(getopt -q ab:cd "$@")
bash
1 #!/bin/bash
2
3 set -- $(getopt -q ab:cd "$@")
4 echo
5 while [ -n "$1" ]
6 do
7 case "$1" in
8 -a) echo "Found the -a option";;
9 -b) param=$2
10 echo "Found the -b, with parameter value $param"
11 shift;;
12 -c) echo "Found the -c";;
13 --) shift
14 break;;
15 *) echo "$1 is not an option"
16 esac
17 shift
18 done
19 count=1
20 for param in "$@"
21 do
22 echo "Parameter #$count: $param"
23 count=$[ $count+1 ]
24 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test14.sh 123 312 -a -b 43 -c -d
Found the -a option
Found the -b, with parameter value '43'
Found the -c
-d is not an option
Parameter #1: '123'
Parameter #2: '312'
getopt命令并不擅长处理带空格和引号的参数值。它会将空格当作参数分隔符,而不是根据双引号将二者当作一个参数。
使用getopts命令
每次调用它时,它一次只处理命令行上检测到的一个参数。处理完所有的参数后,它会退出并返回一个大于0的退出状态码。这让它非常适合用解析命令行所有参数的循环中
bash
getopts optstring variable
有效的选项字母都会列在optstring中,如果选项字母要求有个参数值,就加一个冒号, 要去掉错误消息的话,可以在optstring之前加一个冒号
getopts命令将当前参数保存在命令行中定义的variable中
如果选项需要跟一个参数值, OPTARG环境变量就会保存这个值。
OPTIND环境变量保存了参数列表中getopts正在处理的参数位置。这样你就能在处理完选项之后继续处理其他命令行参数了, 使用
shift $OPIND
bash
1 #!/bin/bash
2 echo
3 while getopts :ab:c opt
4 do
5 case "$opt" in
6 a) echo "Found the -a option";;
7 b) echo "Found the -b option, with value $OPTARG";;
8 c) echo "Found the -c option";;
9 *) echo "Unknow konw option: $opt";;
10 esac
11 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test15.sh -b test -c
Found the -b option, with value test
Found the -c option
会自动减去参数前的-
- 可以处理参数中的空格
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test15.sh -b "Hello world"
Found the -b option, with value Hello world
- 可以吧字母和参数放在一起
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test15.sh -ab"Hello world"
Found the -a option
Found the -b option, with value Hello world
- 把没有定义的值统一转换为?
bash
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test15.sh -d
Unknow konw option: ?
- 处理之后的参数
bash
1 #!/bin/bash
2 echo
3 while getopts :ab:c opt
4 do
5 case "$opt" in
6 a) echo "Found the -a option";;
7 b) echo "Found the -b option, with value $OPTARG";;
8 c) echo "Found the -c option";;
9 *) echo "Unknow konw option: $opt";;
10 esac
11 done
12 shift $[ $OPTIND -1 ]
13 echo
14 count=1
15 for param in "$@"
16 do
17 echo "Parameter $count : $param"
18 count=$[ $count + 1 ]
19 done
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ test15.sh -b test -a -c -d 123 321
Found the -b option, with value test
Found the -a option
Found the -c option
Unknow konw option: ?
Parameter 1 : 123
Parameter 2 : 321
将选项标准化
Linux定义了一些常用的选型的含义
选项 | 描述 |
---|---|
-a | 显示所有对象 |
-c | 生成一个计数 |
-d | 指定一个目录 |
-e | 扩展一个对象 |
-f | 指定读入数据的文件 |
-h | 显示命令的帮助信息 |
-i | 忽略文本大小写 |
-l(小写L) | 产生输出的长格式版本 |
-n | 使用非交互模式(批处理) |
-o | 将所有输出重定向到的指定的输出文件 |
-q | 以安静模式运行 |
-r | 递归地处理目录和文件 |
-s | 以安静模式运行 |
-v | 生成详细输出 |
-x | 排除某个对象 |
-y | 对所有问题回答yes |
获得用户的输入
交互性更强一些, 使用read命令
基本的读取
收到输入之后, read会把数据放到一个变量
bash
1 #!/bin/bash
2
3 echo -n "Enter your name: "
4 read name
5 echo "Hello $name, welcome to my program"
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ myts.sh test16.sh
Enter your name: niubi
Hello niubi, welcome to my program
可以使用-p直接在删除
之中输入提示
输入的参数会依次放入之后的变量之中, 多出来的参数放入最后一个变量
要是不指定变量, 最后都会被放入环境变量REPLY中
超时
可以使用-t来给脚本加入一个定时器, 确定了输入的秒数, 计时器过期之后返回一个非0的状态码
bash
1 #!/bin/bash
2 if read -t 5 -p "Please enter your name: " name
3 then
4 echo "Hello $name, welcome"
5 else
6 echo
7 echo "Sorry , too slow"
8 fi
也可以设置字符的上限, 超过之后自动退出并赋值
bash
1 #!/bin/bash
2 read -n1 -p "Do you want to continue [Y/N]" answer
3 case $answer in
4 Y | y) echo
5 echo "fine, continue on ...";;
6 N | n) echo
7 echo OK, Googbye
8 exit;;
9 esac
10 echo "End"
隐藏方式读取
在输入密码的时候, -s, 会把字体显示为背景的颜色
bash
1 #!/bin/bash
2
3 read -s -p "Enter your passwd: " pass
4 echo
5 echo "Is you passwd reallu $pass?"
jiao@jiao-virtual-machine:~/桌面/linux-shell/14$ myts.sh test21.sh
Enter your passwd:
Is you passwd reallu 123456?
从文件中读取数据
每次会读取一行的内容, 没有内容的时候返回一个非零的返回值
最常用的是是使用管道把cat的参数传递
bash
1 #!/bin/bash
2
3 count=1
4 cat test | while read line
5 do
6 echo "Line $count: $line"
7 count=$[ $count+1 ]
8 done
9 echo "Finish processing the file"