1命令行参数

1.1读取参数

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

例子:计算阶乘

  1. $ vim test1.sh
  2. #!/bin/bash
  3. # using one command line parameter
  4. factorial=1
  5. for (( number = 1; number <= $1 ; number++ ))
  6. do
  7. factorial=$[ $factorial * $number ]
  8. done
  9. echo The factorial of $1 is $factorial
  10.  
  11. $ ./test1.sh 5
  12. The factorial of 5 is 120

1.2读取脚本名

以用$0参数获取shell在命令行启动的脚本名。

  1. $ cat test5.sh
  2. #!/bin/bash
  3. # Testing the $0 parameter
  4. echo The zero parameter is set to: $0
  5.  
  6. $bash test5.sh
  7. The zero parameter is set to: test5.sh

但是这里存在一个潜在的问题。如果使用另一个命令来运行shell脚本,命令会和脚本名混在一起,出现在$0参数中。比如:

  1. $ ./test5.sh
  2. The zero parameter is set to: ./test5.sh
  3. $ bash /home/Christine/test5.sh
  4. The zero parameter is set to: /home/Christine/test5.sh

这个时候basename命令可以帮助我们,basename命令会返回不包含路径的脚本名。

  1. $ cat test5b.sh
  2. #!/bin/bash
  3. # Using basename with the $0 parameter
  4. name=$(basename $0)
  5. echo echo The script name is: $name
  6.  
  7. $ bash /home/Christine/test5b.sh
  8. The script name is: test5b.sh
  9.  
  10. $ ./test5b.sh
  11. The script name is: test5b.sh

可以用这种方法来编写基于脚本名执行不同功能的脚本。这里有个简单的例子:

  1. $ cat test6.sh
  2. #!/bin/bash
  3. name=$(basename $0)
  4. #判断参数是否为空,如果为空的话(就是执行脚本时少带了参数),后面的脚本会报错
  5. if [ -e $1 ]
  6. then
  7. echo "\$1 is empty"
  8. exit 1
  9. elif [ -e $2 ]
  10. then
  11. echo "\$2 is empty"
  12. exit 1
  13. fi
  14.  
  15. if [ $name = "addem" ]
  16. then
  17. total=$[ $1 + $2 ]
  18. elif [ $name = "multem" ]
  19. then
  20. total=$[ $1 * $2 ]
  21. fi
  22. echo The calculated value is $total
  23.  
  24. 开始测试:
  25. $ cp test6.sh addem
  26. $ chmod u+x addem
  27. $ ln -s test6.sh multem
  28. $ ls -l *em
  29. -rwxrw-r--. 1 Christine Christine 224 Jun 30 23:50 addem
  30. lrwxrwxrwx. 1 Christine Christine 8 Jun 30 23:50 multem -> test6.sh
  31.  
  32. $ ./addem 2 5
  33. The calculated value is 7
  34.  
  35. $ ./multem 2 5
  36. The calculated value is 10

本例从test6.sh脚本中创建了两个不同的文件名:一个通过复制文件创建(addem),另一个通过链接创建(multem)。在两种情况下都会先获得脚本的基本名称,然后根据该值执行相应的功能。

2特殊参数变量

2.1参数统计

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

  1. $ cat test8.sh
  2. #!/bin/bash
  3. # getting the number of parameters
  4. echo There were $# parameters supplied.
  5.  
  6. $ ./test8.sh
  7. There were 0 parameters supplied.
  8.  
  9. $ ./test8.sh 1 2 3 4 5
  10. There were 5 parameters supplied.
  11.  
  12. $ ./test8.sh 1 2 3 4 5 6 7 8 9 10
  13. There were 10 parameters supplied.
  14.  
  15. $ ./test8.sh "Rich Blum"
  16. There were 1 parameters supplied.

如果要直接获取最后一个参数的值时,不应该用${$#},而是应该用${!#}:

2.2抓取所有的数据

$*和$@变量可以用来轻松访问所有的参数。这两个变量都能够在单个变量中存储所有的命令行参数。

$*变量会将命令行上提供的所有参数当作一个单词保存,这个单词包含了命令行中出现的每一个参数值;

$@变量会将命令行上提供的所有参数当作同一字符串中的多个独立的单词。

例子:

  1. $ cat test10.sh
  2. #!/bin/bash
  3. # Grabbing the last parameter
  4. params=$#
  5. echo echo The last parameter is $params
  6. echo The last parameter is ${!#}
  7.  
  8. $ bash test10.sh 1 2 3 4 5
  9. The last parameter is 5
  10. The last parameter is 5
  11.  
  12. $ bash test10.sh
  13. The last parameter is 0
  14. The last parameter is test10.sh

3移动变量

shift命令能够用来操作命令行参数。它会根据相对位置来移动命令行参数。在使用shift命令时,默认情况下它会将每个参数变量向左移动一个位置。所以,变量$3的值会移到$2中,变量$2的值会移到$1中,而变量$1的值则会被删除(注意,变量$0的值,也就是程序名,不会改变)。

  1. $ cat test13.sh
  2. #!/bin/bash
  3. count=1
  4. while [ -n "$1" ]
  5. do
  6. echo "Parameter #$count = $1"
  7. count=$[ $count + 1 ]
  8. shift
  9. done
  10.  
  11. $ ./test13.sh rich barbara katie jessica
  12. Parameter #1 = rich
  13. Parameter #2 = barbara
  14. Parameter #3 = katie
  15. Parameter #4 = jessica

另外,你也可以一次性移动多个位置,只需要给shift命令提供一个参数,指明要移动的位置数就行了。

  1. $ cat test14.sh
  2. #!/bin/bash
  3. echo "The original parameters: $*"
  4. shift 2
  5. echo "Here's the new first parameter: $1"
  6.  
  7. $ ./test14.sh 1 2 3 4 5
  8. The original parameters: 1 2 3 4 5
  9. Here's the new first parameter: 3

4处理选项

1. 处理简单选项

  1. $ cat test15.sh
  2. #!/bin/bash
  3. # extracting command line options as parameters
  4. while [ -n "$1" ]
  5. do
  6. case "$1" in
  7. -a) echo "Found the -a option" ;;
  8. -b) echo "Found the -b option" ;;
  9. -c) echo "Found the -c option" ;;
  10. *) echo "$1 is not an option" ;;
  11. esac
  12. shift
  13. done
  14.  
  15. $ ./test15.sh -a -b -c -d
  16. Found the -a option
  17. Found the -b option
  18. Found the -c option
  19. -d is not an option

2. 分离参数和选项

双破折线(--):表明选项列表结束。

  1. $ cat test16.sh
  2. #!/bin/bash
  3. while [ -n "$1" ]
  4. do
  5. case "$1" in
  6. -a) echo "Found the -a option" ;;
  7. -b) echo "Found the -b option";;
  8. -c) echo "Found the -c option" ;;
  9. --) shift
  10. break ;;
  11. *) echo "$1 is not an option";;
  12. esac
  13. shift
  14. done
  15. count=1
  16. for param in $@
  17. do
  18. echo "Parameter #$count: $param"
  19. count=$[ $count + 1 ]
  20. done
  21.  
  22. $ ./test16.sh -c -a -b test1 test2 test3
  23. Found the -c option
  24. Found the -a option
  25. Found the -b option
  26. test1 is not an option
  27. test2 is not an option
  28. test3 is not an option
  29.  
  30. $ ./test16.sh -c -a -b -- test1 test2 test3
  31. Found the -c option
  32. Found the -a option
  33. Found the -b option
  34. Parameter #1: test1
  35. Parameter #2: test2
  36. Parameter #3: test3

3. 处理带值的选项

  1. $ cat test17.sh
  2. #!/bin/bash
  3. while [ -n "$1" ]
  4. do
  5. case "$1" in
  6. -a) echo "Found the -a option";;
  7. -b) param="$2"
  8. echo "Found the -b option, with parameter value $param"
  9. shift ;;
  10. -c) echo "Found the -c option";;
  11. --) shift
  12. break ;;
  13. *) echo "$1 is not an option";;
  14. esac
  15. shift
  16. done
  17. count=1
  18. for param in "$@"
  19. do
  20. echo "Parameter #$count: $param"
  21. count=$[ $count + 1 ]
  22. done
  23.  
  24. $ ./test17.sh -a -b test1 -d
  25. Found the -a option
  26. Found the -b option, with parameter value test1
  27. -d is not an option

但是这种脚本遇到$ ./test17.sh -ac的命令九九没法执行了。

5将选项标准化

选  项

描  述

-a

显示所有对象

-c

生成一个计数

-d

指定一个目录

-e

扩展一个对象

-f

指定读入数据的文件

-h

显示命令的帮助信息

-i

忽略文本大小写

-l

产生输出的长格式版本

-n

使用非交互模式(批处理)

-o

将所有输出重定向到的指定的输出文件

-q

以安静模式运行

-r

递归地处理目录和文件

-s

以安静模式运行

-v

生成详细输出

-x

排除某个对象

-y

对所有问题回答yes

6获得用户输入

6.1基本的读取

read命令从标准输入(键盘)或另一个文件描述符中接受输入。在收到输入后,read命令会将数据放进一个变量

  1. $ cat test22.sh
  2. #!/bin/bash
  3. # testing the read -p option
  4. read -p "Please enter your age: " age
  5. days=$[ $age * 365 ]
  6. echo "That makes you over $days days old! "
  7.  
  8. $ ./test22.sh
  9. Please enter your age: 10
  10. That makes you over 3650 days old!

6.2 超时

使用read命令时要当心。脚本很可能会一直苦等着脚本用户的输入。如果不管是否有数据输入,脚本都必须继续执行,你可以用-t选项来指定一个计时器。-t选项指定了read命令等待输入的秒数。当计时器过期后,read命令会返回一个非零退出状态码。

  1. $ cat test25.sh
  2. #!/bin/bash
  3. # timing the data entry
  4. if read -t 5 -p "Please enter your name: " name
  5. then
  6. echo "Hello $name, welcome to my script"
  7. else
  8. echo
  9. echo "Sorry, too slow! "
  10. fi
  11.  
  12. $ ./test25.sh
  13. Please enter your name: Rich
  14. Hello Rich, welcome to my script
  15.  
  16. $ ./test25.sh
  17. Please enter your name:
  18. Sorry, too slow!

如果计时器过期,read命令会以非零退出状态码退出,可以使用如if-then语句或while循环这种标准的结构化语句来理清所发生的具体情况。

也可以不对输入过程计时,而是让read命令来统计输入的字符数。当输入的字符达到预设的字符数时,就自动退出,将输入的数据赋给变量。

  1. $ cat test26.sh
  2. #!/bin/bash
  3. # getting just one character of input
  4. read -n1 -p "Do you want to continue [Y/N]? " answer
  5. case $answer in
  6. Y | y) echo "fine, continue on…";;
  7. N | n) echo "OK, goodbye"
  8. exit;;
  9. esac
  10. echo "This is the end of the script"
  11.  
  12. $ ./test26.sh
  13. Do you want to continue [Y/N]? Y
  14. fine, continue on
  15. This is the end of the script
  16.  
  17. $ ./test26.sh
  18. Do you want to continue [Y/N]? n
  19. OK, goodbye

本例中将-n选项和值1一起使用,告诉read命令在接受单个字符后退出。只要按下单个字符回答后,read命令就会接受输入并将它传给变量,无需按回车键。

Shell编程—用户输入的更多相关文章

  1. Shell 读取用户输入

    14.2  读取用户输入 14.2.1  变量 上一章我们谈到如何定义或取消变量,变量可被设置为当前shell的局部变量,或是环境变量.如果您的shell脚本不需要调用其他脚本,其中的变量通常设置为脚 ...

  2. shell获取用户输入

    主题: 再学shell之获取用户输入echo -n(不换行)和read命令-p(提示语句) -n(字符个数) -t(等待时间) -s(不回显) 和“读文件”深入学习 1.基本读取read命令接收标准输 ...

  3. linux shell获取用户输入

    一.获取用户输入1.基本读取read命令接收标准输入的输入,或其它文件描述符的输入.得到输入后,read命令将数据输入放入一个标准变量中.[root@rac2 ~]# cat t8.sh #!/bin ...

  4. Shell编程笔记

    Shell编程笔记与Windows下熟悉的批处理类似,也可以将一些重复性的命令操作写成一个脚本方便处理.   修改别人的脚本,运行后遇到个问题 setenv: command not found 查证 ...

  5. SHELL编程入门简介

    一.SHELL软件概念和应用场景 1) 学习Linux技术,不是为了学习系统安装.命令操作.用户权限.配置IP.网络管理,学习Linux技术重点:基于Linux系统部署和维护各种应用软件.程序(Apa ...

  6. shell编程中用户输入处理(shell 04)

    shell编程中用户输入处理1.命令行参数2.脚本运行时获取输入 命令行参数 通过空格来进行分割的位置参数 :$+position $0,$1,$2 ....$0 :程序名$1,$2,$3 ... $ ...

  7. 《Linux命令行与shell脚本编程大全》第十四章 处理用户输入

    有时还会需要脚本能够与使用者交互.bash shell提供了一些不同的方法来从用户处获得数据, 包括命令行参数,命令行选项,以及直接从键盘读取输入的能力. 14.1 命令行参数 就是添加在命令后的数据 ...

  8. 一、Vim编辑器 二、用户和组管理 三、软件的安装(jdk,mysql) 四、Shell编程

    一.Vim编辑器的使用 1. vim编辑器的运行模式 编辑模式:等待用户编辑命令的输入 插入模式:编辑文本内容 命令模式:执行命令 2. 使用 :vim 文件名 3. 查看当前vim编辑器介绍:vim ...

  9. centos 下建用户 shell编程

    useradd 用户名 passwd 用户名 cat /etc/passwd  查看用户信息 删除用户 userdel -r   加一个 -r 表示把用户及用户的主目录都删除 su  切换用户 sud ...

随机推荐

  1. Python os.fchown() 方法

    概述 os.fchown() 方法用于修改一个文件的所有权,这个函数修改一个文件的用户ID和用户组ID,该文件由文件描述符fd指定.高佣联盟 www.cgewang.com Unix上可用. 语法 f ...

  2. 苹果挖矿恶意程序处理(OSX/CoinMiner.X)

    背景 近期通过流量告警发现多起外连矿池的告警,均外连至43.249.204.231 威胁情报信息如下: 系统表象 1.通过ps -ef|grep osascript发现在/library/Launch ...

  3. __getattribute__和item系列

    # class Foo: # def __init__(self,x): # self.x=x # # def __getattr__(self, item): # print('执行的是我') # ...

  4. json&pickle&shelve

    之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了 ...

  5. HIVE常用正则函数(like、rlike、regexp、regexp_replace、regexp_extract)

    Oralce中regex_like和hive的regexp对应 LIKE 语法1: A LIKE B 语法2: LIKE(A, B) 操作类型: strings 返回类型: boolean或null ...

  6. webMvcConfigurer的详情

                  摘要 Spring的WebMvcConfigurer接口提供了很多方法让我们来定制SpringMVC的配置.而且Spring还提供了WebMvcConfigurerAdap ...

  7. 基于OpenSIPS做注册服务下,场景A打B,一方发起BYE挂断后收到500,另一方无法挂断的问题

    基于OpenSIPS做注册服务下,场景A打B,一方发起BYE挂断后收到500,另一方无法挂断的问题     最近在工作中遇到一个看似很奇怪的,排除起来很费劲,但最后的解决方式又及其简单的问题,下面我们 ...

  8. Python 面向对象之高级编程

    7.面向对象高级编程 7.1使用__slots__ python动态语言,new 对象后绑定属性和方法 Tip:给一个实例绑定的方法,对其他对象无效.可以通过对class绑定后,所有对象可以调用该方法 ...

  9. 小白入门Web前端开发学习一周小结

    说之前还是先说点其他的,简单介绍下自己为何选择web前端开发: 本人之前在一家国企单位从事质检工作,干了3年,工资和待遇还算不错,但由于其工作的流动性导致知识的脱轨以及精神上的空缺,最后还是打算在25 ...

  10. 动态路由 - EIGRP

    EIGRP 特性 EIGRP(增强内部网关路由协议)是思科的私有协议,属于距离矢量路由协议,但又具有链路状态的特性.并且支持 VLSM(可变长子网和无类路由协议).但在本质上说还是传送路由条目. 具有 ...