Linux Shell脚本编写——使用结构化命令(四)

命令行参数

向shell脚本传数据的最基本方法是使用命令行参数,命令行参数允许在运行脚本时向命令行添加数据值

读取参数

bash shell会将一些称为位置参数的特殊变量分配给命令行输入的所有参数,甚至包括shell执行的程序的名字,$0是程序名,$1是第一个参数,$2是第二个参数

代码4-1

[email protected]:/data# cat demo1
#!/bin/bash
factorial=1
for ((i=1;i<=$1;i++))
do
        factorial=$[ $factorial * $i ]
done
echo "The factorial of $1 is $factorial"
[email protected]:/data# ./demo1 5
The factorial of 5 is 120

  

输入更多的命令项用空格分开

代码4-2

[email protected]:/data# cat demo2
#!/bin/bash
sum=$[ $1 + $2 ]
echo "The first parameter is $1"
echo "The second parameter is $2"
echo "The sum is $sum"
[email protected]:/data# ./demo2 3 5
The first parameter is 3
The second parameter is 5
The sum is 8

当输入为字符串时如果存在空格,必须使用单引号或双引号

代码4-3  

[email protected]:/data# cat demo3
#!/bin/bash
echo "Hello $1,glad to meet you"
echo "Hello $2,glad to meet you"
[email protected]:/data# ./demo3 John "Rich blum"
Hello John,glad to meet you
Hello Rich blum,glad to meet you

  

如果脚本需要多于9哥命令行参数,需要在数字周围加上花括号如:${10}、${11}

代码4-4

[email protected]:/data# cat demo4
#!/bin/bash
sum=$[ $10 + $11 ]
echo "The tenth paramter is ${10}"
echo "The eleventh paramter is ${11}"
echo "The sum is $sum"
[email protected]:/data# ./demo4 1 2 3 4 5 6 7 8 9 10 11
The tenth paramter is 10
The eleventh paramter is 11
The sum is 21

  

当传给$0变量的真实字符串是整个脚本的路径时,程序中就会使用整个路径,而不仅仅是程序名

代码4-5

[email protected]:/data# cat demo5
#!/bin/bash
echo "The command entered is : $0"
[email protected]:/data# /data/demo5
The command entered is : /data/demo5
[email protected]:/data# ./demo5
The command entered is : ./demo5

  

basename命令只返回程序名而不包括路径

代码4-6

[email protected]:/data# cat addem
#!/bin/bash
name=`basename $0`
if [ $name = "addem" ]
then
        total=$[ $1 + $2 ]
elif [ $name = "multem" ]
then
        total=$[ $1 * $2 ]
fi
echo "The total is $total"
[email protected]:/data# ./addem 2 5
The total is 7
[email protected]:/data# cp -s addem multem
[email protected]:/data# ./multem 2 5
The total is 10

  

可以使用-n检查命令行参数中是否有数据,如果要对命令行参数进行字符串比较最好加上双引号

代码4-7

[email protected]:/data# cat demo6
#!/bin/bash
if [ -n "$1" ]
then
        echo "Hello,$1"
else
        echo "Sorry, you did not identify yourself"
fi
[email protected]:/data# ./demo6 Tom
Hello,Tom
[email protected]:/data# ./demo6
Sorry, you did not identify yourself

  

$#特殊变量含有脚本运行时就有的命令行参数的个数

代码4-8

[email protected]:/data# cat demo1
#!/bin/bash
echo "There were $# parameters supplied"
[email protected]:/data# ./demo1 1 2 3 4 5
There were 5 parameters supplied
[email protected]:/data# ./demo1 Tom "Hello World"
There were 2 parameters supplied

  

代码4-9

[email protected]:/data# cat demo2
#!/bin/bash
if [ $# != 2 ]
then
        echo "Usage:demo2 a b"
else
        sum=$[ $1 + $2 ]
        echo "The sum is $sum"
fi
[email protected]:/data# ./demo2
Usage:demo2 a b
[email protected]:/data# ./demo2 3
Usage:demo2 a b
[email protected]:/data# ./demo2 3 5
The sum is 8
[email protected]:/data# ./demo2 3 5 8
Usage:demo2 a b

注:$#虽然代表命令行参数的个数,但${$#}并不能显示最后一个命令行参数的变量

使用${!#}可以显示最后一个参数,或者将$#赋给一个变量param,然后也按特殊命令行参数变量的格式使用了该变量。但要注意的是,当命令行上没有任何参数时,$#的值为0,但${!#}变量会返回命令行用到的脚本名

代码4-10

[email protected]:/data# cat demo3
#!/bin/bash
echo "The last parameter was $#"
echo "The last parameter was ${!#}"
[email protected]:/data# ./demo3
The last parameter was 0
The last parameter was ./demo3
[email protected]:/data# ./demo3 1 2 3 4 5 6
The last parameter was 6
The last parameter was 6

  

$*和[email protected]变量提供了对所有参数的快速访问,$*变量会将命令行上提供的所有参数当做单个单词保存,[email protected]变量会将命令行上提供的所有参
数当做同一个字符串中多个独立的单词

代码4-11

[email protected]:/data# cat demo4
#!/bin/bash
count=1
for param in "$*"
do
        echo "\$* Parameter #$count = $param"
        ((count++))
done
count=1
echo "——————————————————————"
for param in "[email protected]"
do
        echo "\[email protected] Parameter #$count = $param"
        ((count++))
done
[email protected]:/data# ./demo4 Hadoop Spring MyBatis Hibernate Shiro
$* Parameter #1 = Hadoop Spring MyBatis Hibernate Shiro
——————————————————————
[email protected] Parameter #1 = Hadoop
[email protected] Parameter #2 = Spring
[email protected] Parameter #3 = MyBatis
[email protected] Parameter #4 = Hibernate
[email protected] Parameter #5 = Shiro

  

shift命令默认情况下它会将每个参数变量的索引值减1,所以,变量$3的值会移到$2,变量$2的值会移到$1,而变量$1的值则会被删除
(变量$0的值,也就是程序名不会变),每执行一次shift命令,所有参数的位置移动一位

代码4-12

[email protected]:/data# cat demo5
#!/bin/bash
count=1
while [ -n "$1" ]
do
        echo "Parameter #$count = $1"
        ((count++))
        shift
done
[email protected]:/data# ./demo5 Hadoop Spring MyBatis Hibernate Shiro
Parameter #1 = Hadoop
Parameter #2 = Spring
Parameter #3 = MyBatis
Parameter #4 = Hibernate
Parameter #5 = Shiro

  

也可以给shift命令提供一个参数来执行多位移动

代码4-13

[email protected]:/data# cat demo6
#!/bin/bash
echo "The original parameters : $*"
shift 2
echo "Here‘s the new first parameter : $1"
[email protected]:/data# ./demo6 1 2 3 4 5 6
The original parameters : 1 2 3 4 5 6
Here‘s the new first parameter : 3

  

处理选项,选项是跟在单破折线后面的单个字母,能改变命令的行为

shell用特殊字符(--)双破折线来表明选项结束了,将剩余命令行参数交给后续程序处理

代码4-14

[email protected]:/data# cat demo1
#!/bin/bash
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 "[email protected]"
do
        echo "Parameter #$count : $param"
        ((count++))
done
[email protected]:/data# ./demo1 -a -b -c test1 test2 test3
Found the -a option
Found the -b option
Found the -c option
test1 is not an option
test2 is not an option
test3 is not an option
[email protected]:/data# ./demo1 -a -b -c -- test1 test2 test3
Found the -a option
Found the -b option
Found the -c option
Parameter #1 : test1
Parameter #2 : test2
Parameter #3 : test3

  

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

getopt optstring options parameters

optstring定义了命令行有效的选项字母,每个需要参数值的选项字母后加一个冒号

代码4-15

[email protected]:/data# getopt ab:cd -ab test1 -cd test2 test3
 -a -b test1 -c -d -- test2 test3

如代码4-15所示,optstring定义了4哥有效选项字母,a、b、c和、d。它还定义了选项字母b需要一个参数值,当getopt 命令运行时,它会检查提供的参数列表,并基于optstring解析。它会自动将-cd选项分成两个单独的选项,并插入双破折线分开航中的额外参数

如代码4-16,如果置顶一个不在optstring中的选项,默认情况下,getopt 命令会产生一条错误的信息,加上-q则可以忽略这条信息:

代码4-16

[email protected]:/data# getopt ab:cd -ab test1 -cde test2 test3
getopt: invalid option -- ‘e‘
 -a -b test1 -c -d -- test2 test3
[email protected]:/data# getopt -q ab:cd -ab test1 -cde test2 test3
 -a -b ‘test1‘ -c -d -- ‘test2‘ ‘test3‘

  

set命令的选项之一是双破折线,该方法会将原始的脚本的命令行参数传给getopt命令,之后再将getopt的输出传给set命令,set会将命令行参数值替换成传递给它的值

代码4-17

[email protected]:/data# cat demo2
#!/bin/bash
set -- `getopt -q ab:c "[email protected]"`
while [ -n "$1" ]
do
        case "$1" in
        -a) echo "Found the -a option";;
        -b) param="$2"
            echo "Found -b option. with parameter value $param"
            shift;;
        -c) echo "Found the -c option";;
        --) shift
            break;;
        *)  echo "$1 is not a option"
        esac
        shift
done

count=1
for param in "[email protected]"
do
        echo "Parameter #$count : $param"
        ((count++))
done
[email protected]:/data# ./demo2 -ac
Found the -a option
Found the -c option
[email protected]:/data# ./demo2 -ab test1 -cd "test2 test3" test4 test5
Found the -a option
Found -b option. with parameter value ‘test1‘
Found the -c option
Parameter #1 : ‘test2
Parameter #2 : test3‘
Parameter #3 : ‘test4‘
Parameter #4 : ‘test5‘

从代码4-17可以看出,getopt命令并不擅长处理带空格的参数值,它会将空格当作参数分隔符,而不是根据双引号将二者当作一个参数,幸而,可以使用getopts解决这一问题  

getopts在每次调用它时,只处理一个命令行上检测到的参数。处理完所有参数后,它会退出并返回一个大于0的退出状态码

getopts optstring variable

getopts 中的optstring 与之前类似,如果选项字母要求有参数值的话,就加一个冒号,如果要去掉错误信息的话,就在optstring 之前加一个冒号

getopts 命令会用到两个环境变量。如果选项需要跟一个参数值,OPTARG环境变量就会保存这个值。OPTIND环境变量保存了参数列表中getopts 正在处理的参数位置

代码4-18

[email protected]:/data# cat demo3
#!/bin/bash
while getopts :ab:c opt
do
        case "$opt" in
        a) echo "Found the -a option";;
        b) echo "Fount the -b option, with value $OPTARG";;
        c) echo "Found the -c option";;
        *) echo "Unknow option : $opt ";;
        esac
done
[email protected]:/data# ./demo3 -ab test1 -c
Found the -a option
Fount the -b option, with value test1
Found the -c option
[email protected]:/data# ./demo3 -b "test1 test2" -a
Fount the -b option, with value test1 test2
Found the -a option
[email protected]:/data# ./demo3 -d
Unknow option : ?
[email protected]:/data# ./demo3 -acde
Found the -a option
Found the -c option
Unknow option : ?
Unknow option : ?
[email protected]:/data# ./demo3 -abtest1
Found the -a option
Fount the -b option, with value test1

如代码4-18,getopts可以很好的处理包含空格的参数值,能够将命令行上找到的所有未定义的选项统一输出成问号,optstring 中未定义的选项字母会以问号形式发送给代码,同时可以将选项字母和参数值放一起使用而不用加空格

OPTIND和shift命令一起使用来移动参数

代码4-19

[email protected]:/data# cat demo4
#!/bin/bash
while getopts :ab:cd opt
do
        case "$opt" in
        a) echo "Found the -a option";;
        b) echo "Fount the -b option, with value $OPTARG";;
        c) echo "Found the -c option";;
        d) echo "Found the -d option";;
        *) echo "Unknow option : $opt ";;
        esac
done
shift $[ $OPTIND - 1 ]
count=1
for param in "[email protected]"
do
        echo "Parameter $count : $param"
        ((count++))
done
[email protected]:/data# ./demo4  -ab test1 -d test2 test3 test4
Found the -a option
Fount the -b option, with value test1
Found the -d option
Parameter 1 : test2
Parameter 2 : test3
Parameter 3 : test

  

获取用户输入

read命令接受从标准输入后,会将数据放进一个标准变量

代码4-20

[email protected]:/data# cat demo5
#!/bin/bash
echo -n "Enter your name:"
read name
echo "Hello $name, welcome to my program"
[email protected]:/data# ./demo5
Enter your name:Tom
Hello Tom, welcome to my program

  

read命令包含-p选项,允许在字符串后接收参数 ,参数与字符串必须用空格分隔

代码4-21

[email protected]:/data# cat demo1
#!/bin/bash
read -p "Enter your name:" first last
echo "Your name is $last. $first..."
[email protected]:/data# ./demo1
Enter your name:Rich Blum
Your name is Blum. Rich...

  

读取多个输入

代码4-22

[email protected]:/data# cat demo6
#!/bin/bash
read -p "Please enter your age:" age
days=$[ $age * 365 ]
echo "That makes you over $days daysold"
[email protected]:/data# ./demo6
Please enter your age:20
That makes you over 7300 daysold

  

如果read命令行中不指定变量,会将接收到的数据都存放进特殊环境变量REPLY中

代码4-23

[email protected]:/data# cat demo2
#!/bin/bash
read -p "Enter a number:"
factorial=1
for ((i=1;i<=$REPLY;i++))
do
        factorial=$[ $factorial * $i ]
done
echo "The factorial of $REPLY is $factorial"
[email protected]:/data# ./demo2
Enter a number:5
The factorial of 5 is 120

  

代码4-24

[email protected]:/data# cat demo3
#!/bin/bash
read -p "Enter your parameter:"
echo "Your parameter:$REPLY"
[email protected]:/data# ./demo3
Enter your parameter:6
Your parameter:6
[email protected]:/data# ./demo3
Enter your parameter:8 9
Your parameter:8 9

  

read命令如果没有输入就会一直等下下去,可加-t选项来指定一个计时器,当计时器过后,read会返回一个非0状态码

代码4-25

[email protected]:/data# cat demo4
#!/bin/bash
echo "time:`date "+%Y-%m-%d %H:%M:%S"`"
if read -t 5 -p "Please enter your name:" name
then
        echo "Hello $name, welcome to my script time:`date "+%Y-%m-%d %H:%M:%S"` "
else
        echo "Sorry, too slow! time:`date "+%Y-%m-%d %H:%M:%S"`"
fi
[email protected]:/data# ./demo4
time:2016-12-04 16:06:06
Please enter your name:Tom
Hello Tom, welcome to my script time:2016-12-04 16:06:08
[email protected]:/data# ./demo4
time:2016-12-04 16:06:12
Please enter your name:Sorry, too slow! time:2016-12-04 16:06:17

  

可以用read命令来对输入的字符计数,当输入的字符达到预设的字符数时,它会自动将输入的数据赋给变量并开始执行往下的程序,将-n
和1一起使用,告诉read命令在接受单个字符后退出

代码2-25

[email protected]:/data# cat demo5
#!/bin/bash
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
echo "This is the end of the script"
[email protected]:/data# ./demo5
Do you want to continue [Y/N]y
Fine,continue on...
This is the end of the script

  

隐藏方式读取,-s选项会阻止将传给read命令的数据显示在显示器上(实际数据会显示,只是read命令会将文本颜色设成跟背景色一样)

代码2-26

[email protected]:/data# cat demo6
#!/bin/bash
read -s -p "Enter your password:" pass
echo
echo "Is your password really $pass"
[email protected]:/data# ./demo6
Enter your password:
Is your password really hello

  

将cat的结果通过管道输出给read

代码2-17

[email protected]:/data# cat text
Spring
MyBatis
Hibernate
Shiro
Hadoop
Spark
[email protected]:/data# cat demo1
#!/bin/bash
count=1
cat text | while read line
do
        echo "Line $count:$line"
        ((count++))
done
[email protected]:/data# ./demo1
Line 1:Spring
Line 2:MyBatis
Line 3:Hibernate
Line 4:Shiro
Line 5:Hadoop
Line 6:Spark

  

时间: 2024-10-25 03:07:44

Linux Shell脚本编写——使用结构化命令(四)的相关文章

Linux Shell脚本编写——使用结构化命令(二)

结构化命令中,最基本的类型就是if-then语句 if command then command fi bash shell的if语句会执行if行定义的那个命令,如果命令的退出状态码是0,则代表成功执行,位于then部分的命令就会执行.如果if行定义的命令的退出状态码是其他,则then部分的命令将不会执行,且if-then语句不能测试跟命令的退出状态码无关的条件 代码2-1 [email protected]:/data# cat demo1 #!/bin/bash if date then e

Linux Shell脚本编写——使用结构化命令(三)

for命令 for var in listdo commandsdone 代码2-1 [email protected]:/data# cat demo1 #!/bin/bash for test in Alabama Alaska Arizona Arkansas "California Colorado" do echo "The next state is $test" done echo "The last state we visited was

shell脚本编程-使用结构化命令(if/else)(转)

11.1 使用if-then语句 格式如下 if语句会执行if行定义的那个命令,如果该命令的退出状态码是0,则then部分的语句就会执行,其他值,则不会 1 2 3 4 if command then commands fi 在要执行的命令结尾加个分号,就能在同一行使用then语句了,格式如下 1 2 3 if command; then commands fi 11.2 if-then-else语句 格式如下: 1 2 3 4 5 6 if command then commands else

Linux Shell脚本入门--cut命令

Linux Shell脚本入门--cut命令 cut cut 命令可以从一个文本文件或者文本流中提取文本列. cut语法 [[email protected] ~]# cut -d'分隔字符' -f fields <==用于有特定分隔字符 [[email protected] ~]# cut -c 字符区间 <==用于排列整齐的信息 选项与参数: -d :后面接分隔字符.与 -f 一起使用: -f :依据 -d 的分隔字符将一段信息分割成为数段,用 -f 取出第几段的意思: -c :以字符 (

老李分享:《Linux Shell脚本攻略》 要点(四)

老李分享:<Linux Shell脚本攻略> 要点(四) 1.IP地址的正则表达式: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 2.grep用法 //在多级目录中对文本进行递归检索 [[email protected] program_test]# grep "yang" ./ -Rn ./test.txt:6:laoyang./right.txt:1:1 yang man //忽略大小写匹配 [[email protec

《Linux Shell脚本攻略》 笔记 第四章:高效文本处理

<Linux Shell脚本攻略> 笔记 第四章:高效文本处理 1.IP地址的正则表达式: [0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3} 2.grep用法 //在多级目录中对文本进行递归检索 [[email protected] program_test]# grep "yang" ./ -Rn ./test.txt:6:laoyang ./right.txt:1:1 yang man //忽略大小写匹配 [[email pr

Linux Shell脚本编写——构建基本脚本(一)

创建shell脚本 在创建shell脚本文件,必须在文件的第一行指定要使用的shell,其格式为: #!/bin/bash 创建.执行sh脚本 代码1-1 [email protected]:/data# cat demo1 #/bin/bash date who [email protected]:/data# ls -l total 4 -rw-r--r-- 1 root root 21 Dec 1 13:59 demo1 [email protected]:/data# chmod u+x

linux shell脚本编写

大家好 这是一篇自己阅读.学习的shell编程,工作中大量应用,尤为awk.sed.grep为主.希望对大家速成有用 可以直接翻看到中部位置 [data] export PATH=/mall/jdk/jdk1.7/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin export LANG=zh_CN.GB18030 start=`date +%s -d "2011-11-28 15:55:37&qu

Linux Shell脚本编写——呈现数据(五)

Linux系统将每个对象当做文件来处理.这包括输入和输出的过程.Linux用文件描述符来标识每个文件对象.文件描述符是一个非负整数,可以唯一地标识会话中打开的文件.每个过程一次最多可以有9个文件描述符.出于特殊目的,bash shell保留了最早的3个文件描述符(0.1和2) Linux的标准文件描述符 文件描述符 缩写 描述 0 STDIN 标准输入 1 STDOUT 标准输出 2 SRDERR 标准错误 STDIN STDIN文件描述代表shell的标准输入.对于终端界面来说,标准输入就是键