常用参数变量
一些常用的参数变量,可以获取传给命令行的参数。
$0 脚本名,带有路径
# 使用 basename 只获取名称
$(basename $0)
$1 ... $9, ${10}, ${11} ...
# 在使用参数前注意检查是否存在
if [ -n "$1" ]
then
...
fi
# 特殊参数变量
$# 获取参数的个数
${!#} 获取最后一个参数。如果没有参数,${!#} 返回的是脚本的名称
# 这种方法也是返回参数的个数,如果没有参数,返回 0
last=$#
echo "The parameter number is $last"
$* 把所有的输入当作一个整体
$@ 会分割输入的参数,可使用 for 循环分别获取
for param in "$@"
do
...
done
传给命令行的参数如果有空格,需要使用引号:
$ ./test.sh "Rich Parker"
shift
命令移动变量
作用:将每个参数变量向左移动一个位置。变量 $0
的值不会变。
如果某个参数被移除,它的值就被丢弃了,无法再恢复。
#!/bin/bash
# shift 后面也可以跟参数,表示一次移动多个
count=1
while [ -n "$1" ]
do
echo "Parameter #$count = $1"
count=$((count+1))
shift
done
# 使用 shift 之后,就无法再获取参数的值了
echo "The second parameter is $2"
# 运行结果是:
$ ./test21-shift.sh rich barbara katie jessica
Parameter #1 = rich
Parameter #2 = barbara
Parameter #3 = katie
Parameter #4 = jessica
The second parameter is
处理选项
命令行选项后面可以带参数;
shell 会用双破折号来表明选项列表结束,在双破折号之后,就可以将剩下的命令行参数当作参数;
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the -a option" ;;
-b) echo "Found the -b option, with parameter value $2"
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
# 测试
$ sh testsh.sh -a -b 23 -c -d -- param1 param2
Found the -a option
Found the -b option, with parameter value 23
Found the -c option
-d is not an option
Parameter #1: param1
Parameter #2: param2
弊端,将多个选项放在一起就不能用了,比如 -ab
使用 getopt
getopt optstring parametrs
optstring 中列出要在脚本中用到的每个命令行选项字母,在每个需要参数值的选项字母后加一个冒号。
$ getopt ab:cd -a -b test1 -cde test2 test3
getopt: illegal option -- e
-a -b test1 -c -d -- test2 test3
如果指定了一个不在 optstring 中的选项,会抛出错误信息,使用 -q
选项可以忽略。
在脚本中使用 getopt
命令:
set
命令的选项之一是双破折号(—),它会将命令行参数替换成 set 命令的命令行值。
# 使用 getopt 处理命令参数
# getopt 处理带空格的参数有问题
set -- $(getopt -q ab:cd "$@")
# 剩下的和上面的处理一样
弊端,处理带空格的参数值有问题,它会将空格当作参数分隔符,而不是根据引号将二者当作一个参数。比如下面这个:
$ ./test.sh -a -b test1 -cd "test2 test3" test4
Found the -a option
Found the -b option, with parameter value test1
Found the -c option
-d is not an option
Parameter #1: test2
Parameter #2: test3
Parameter #3: test4
使用 getopts
getopts optstring variable
每次调用它时,只处理命令行上检测到的一个参数。处理完所有的参数之后,会退出并返回一个大于 0 的退出状态码。
要去掉错误消息的话,可以在 optstring 之前加一个冒号。
用到两个环境变量。如果选项需要跟一个参数值,OPTARG
环境变量就会保存这个值。OPTIND
环境变量保存了参数列表中 getopts 正在处理的参数位置。
#!/bin/bash
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))
count=1
for param in "$@"
do
echo "Parameter #$count: $param"
count=$((count+1))
done
# 使用示例
# 选项可以放在一起
$ ./test23.sh -ab test1 -c
Found the -a option
Found the -b option, with value test1
Found the -c option
# 参数中可以有空格
$ ./test23.sh -ab "test test" -c
Found the -a option
Found the -b option, with value test test
Found the -c option
# 参数和选项不用空格分开
$ ./test23.sh -abtest
ound the -a option
Found the -b option, with value test
# 会将没有定义的选项输出为问号
$ ./test23.sh -acde
Found the -a option
Found the -c option
Unknown option: ?
Unknown option: ?
将选项标准化
有些字母选项在 Linux 世界里已经有了某种程度的标准含义。下表列出了一些常用的 Linux 命令选项:
获取用户输入 read
使用 read
命令:-p
后面跟提示信息,即在输入前打印提示信息-s
安静模式,在输入字符时不再屏幕上显示,例如login时输入密码-n
后跟一个数字,定义输入文本的长度-t
后面跟秒数,定义输入字符的等待时间-r
屏蔽\,如果没有该选项,则\作为一个转义字符,有的话 \就是个正常的字符了
read name
echo "Your name is $name"
# 使用 -p 参数
read -p "Please input your name: " name
echo "Your name is $name"
# read 一次性读入多个变量
read -p "please input two number: " a b
echo "The sum of the two numbers is: $((a+b))"
# 使用 -s 参数,隐藏输入内容
read -s -p "Please input your password: " password
echo "Is your password really $password?"
# read 后面不指定变量,会放在 REPLY 环境变量中
read -p "Enter your name: "
echo "Your name is $REPLY"
# 使用 -t 指定等待的秒数
if read -t 5 -p "Please enter your name: " name
then
echo "Hello $name"
else
echo "Sorry, too slow!"
fi
# 使用 -n 指定输入的字符数。输入的字符数达到指定的值,就会自动回车完成输入
read -n1 -p "Do you want to continue [Y/N]? " answer
case $answer in
Y | y) echo
echo "fine, continue on...";;
N | n) echo
echo "Ok, goodbye"
exit;;
esac
读取文件
可以用 read 命令来读取Linux系统上文件里保存的数据。每次调用 read 命令,它都 会从文件中读取一行文本。当文件中再没有内容时,read命令会退出并返回非零退出状态码。
$ cat test25-read-file.sh
#!/bin/bash
count=1
cat states | while read line
do
echo "Line $count: $line"
count=$((count+1))
done
echo "Finished processing the file"
$ cat states
Alabama
Alaska
Arizona
Arkasas
California
New York
$ sh test25-read-file.sh
Line 1: Alabama
Line 2: Alaska
Line 3: Arizona
Line 4: Arkasas
Line 5: California
Finished processing the file
另一个方式:
$ cat test25-read-file2.sh
#!/bin/bash
input="users.csv"
while IFS=',' read -r userid name
do
echo "adding $userid"
useradd -c "$name" -m "$userid"
done < "$input"
$ cat users.csv
rich,Richard Blum
christine,Christine Bresnahan
barbara,Barbara Blum
$ sh test25-read-file2.sh
adding rich
adding christine
adding barbara
# 查看刚才创建的账号
$ tail -3 /etc/passwd
rich:x:1001:1001:Richard Blum:/home/rich:/bin/bash
christine:x:1002:1002:Christine Bresnahan:/home/christine:/bin/bash
barbara:x:1003:1003:Barbara Blum:/home/barbara:/bin/bash