bash shell 脚本提供了3种从 用户处 获取数据的方法:
- 命令行参数(添加在命令后的数据)
- 命令行选项
- 直接从键盘读取输入
1 命令行参数
像 shell 脚本传递数据的最基本方法是使用 命令行参数.
示例:
./add.sh 10 20
本例向脚本 add.sh 传递了两个 命令行参数(10 和 20).
1.1 读取命令行参数
bash shell 中有一些特殊变量, 被称为 位置参数(positional parameter).
位置参数的标准数字是: $0 是程序名; $1 是第一个参数; $2 是第二个参数; 依次类推, $9 是第九个参数. ${10} 是第十个参数…
看一个求 阶乘(factorial) 的例子:
$ cat temp.sh
#!/bin/bash
factorial=1
for (( i=1; i<=$1; i++)); do
factorial=$[$factorial * $i]
done
echo "the factorial of $1 is $factorial"
$ ./temp.sh 4
the factorial of 4 is 24
如果 shell 脚本需要用到 命令行参数, 但是脚本运行时却没有加 命令行参数, 可能会出问题, 比如上面的例子中, 如不加参数运行会报错:
$ ./temp.sh
./temp.sh: line 3: ((: i<=: syntax error: operand expected (error token is "<=")
the factorial of is 1
一般我们需要检查 命令行参数 , 改造一下上面的例子:
$ cat temp.sh
#!/bin/bash
# 命令行参数1 字符串长度是否是 zero
if [ -z "$1" ]; then
echo "usage: $0 number"
exit 0
fi
factorial=1
for (( i=1; i<=$1; i++)); do
factorial=$[$factorial * $i]
done
echo "the factorial of $1 is $factorial"
$ ./temp.sh
usage: ./temp.sh number
bash shell 还提供了几个特殊的变量: $# 脚本运行时携带的 命令行参数的个数; $* 将命令行上提供的 所有参数 当做 一个单词 保存; $@ 将命令行上提供的 所有参数 当做 多个独立的单词 保存.
示例:
$ cat temp.sh
#!/bin/bash
echo "There wre $# parameters supplied."
count=1
for param in "$*"; do
echo "\$*, 参数$count = $param"
count=$[ $count + 1 ]
done
count=1
for param in "$@"; do
echo "\$@, 参数$count = $param"
count=$[ $count +1 ]
done
$ ./temp.sh miyan rosie abby
There wre 3 parameters supplied.
$*, 参数1 = miyan rosie abby
$@, 参数1 = miyan
$@, 参数2 = rosie
$@, 参数3 = abby
如果把 "$*" 上的双引号 "" 去掉, $* 会输出和 "$@" 一样的结果.
1.2 shell parameter expansion
这里介绍两个常用的 参数扩展 :
${variable_name:-value} : 如果 variable_name 的值为空, 返回 value.${variable_name:?msg} : 如果 variable_name 的值为空, 返回message错误并退出.
示例:
$ cat temp.sh
#!/bin/bash
name=${1:? user name cannot be empty}
password=${2:-$(uuidgen | tr '[:upper:]' '[:lower:]')}
echo "username: $name, passowrd: $password"
$ ./temp.sh
./temp.sh: line 2: 1: user name cannot be empty
$ ./temp.sh miyan
username: miyan, passowrd: e2c7956c-cd6c-4761-a323-a6785587b8f9
2 命令选项
选项(option) 是跟在 破折号(dash - ) 后面的单个字母, 它能改变命令的行为. 处理 选项 涉及到 getopt 和 getopts 命令. 这里从略, 等有需要用到再回来补上.
3 获取用户输入
尽管 命令行选项 和 参数 是从 用户处 获取输入的一种重要方式, 但有时脚本的交互性还需更强一些. 比如在脚本运行时问一个问题, 等待运行脚本的人来回答, bash shell 为此提供了 read 命令.
3.1 read 命令
read variable_name 从标准输入(键盘) 或 另一个文件描述符中 接受输入, 在收到输入后, read 会将数据存入变量中.
read 命令示例:
$ cat temp.sh
#!/bin/bash
# -n, don't output the trailing newline.
echo -n "Enter you name: "
read name
echo "Hello $name"
$ ./temp.sh
Enter you name: miyan
Hello miyan
read 有3个常用 选项 -p , -s 和 -t :
read -p “prompt text” variable_name : -p here stands for the prompt. Here we read the data along with some hint text .read -s variable_name : This option -s means secret or secure whatever is used to read the sensitive data.read -t seconds variable_name : 设置 timeout 时间, 单位秒, 超时返回非 0 退出状态码.
当 read 读取多个变量时, 多个变量用空格分隔:
$ cat temp.sh
#!/bin/bash
read -p "three names: " u1 u2 u3
echo "Hello $u1, $u2, $u3 !!!"
$ ./temp.sh
three names: miyan rosie abby
Hello miyan, rosie, abby !!!
3.2 从文件中读取
read 命令可以读取文件中保存的数据. 每次调用 read 命令, 它都会读取一行文本. 当文件中没有内容时, read 会退出并返回非 0 的 退出状态码.
问题是怎么将文件的数据传给 read ? 最常见的方法是 对文件使用 cat 命令, 将结果通过 管道 直接传给 含有 read 命令的 while 命令.
看个例子:
$ cat test.txt
狂浪生
hotel california
nothing's gonna change my love for you
$ cat temp.sh
#!/bin/bash
count=1
cat test.txt | while read line; do
echo "line $count: $line"
count=$[ $count + 1 ]
done
$ ./temp.sh
line 1: 狂浪生
line 2: hotel california
line 3: nothing's gonna change my love for you
还有一种高级的写法, 用 输入重定向 :
$ cat temp.sh
#!/bin/bash
count=1
while read line; do
echo "line $count: $line"
count=$[ $count + 1 ]
done < test.txt
$ ./temp.sh
line 1: 狂浪生
line 2: hotel california
line 3: nothing's gonna change my love for you
|