通过前几篇文章的学习,我们学会了shell的基本语法。在linux的实际操作中,我们经常看到命令会有很多参数,例如:ls -al 等等,那么这个参数是怎么处理的呢? 接下来我们就来看看shell脚本对于用户输入参数的处理。

命令行参数处理

根据参数位置获取参数

bash shell可根据参数位置获取参数。通过 $1$9 获取第1到第9个的命令行参数。$0为shell名。如果参数超过9个,那么就只能通过${}来获取了, 例如获取第10个参数,那么可以写为${10}。

示例一:

#!/bin/bash
#testinput.sh
echo "file name: $0"
echo "base file name: $(basename $0)"
echo "param1: $1"
echo "param2: ${2}"

运行上面的的shell

./testinput.sh 12 34

最终得到的结果如下:

file name: ./testinput4.sh

base file name: testinput4.sh

param1: 12

param2: 34

成功的得到文件名和命令行输入的参数(命令行参数以空格分隔,如果参数包含了空格,那么久必须添加引号了)

$0默认会获取到当前shell文件的名称,但是,它也包含(./),如果你以完整路径运行,那么这还会包含目录名。因此,上面通过basename命令来获取单纯的文件名$(basename $0)。

试想一下,假如我们写的shell的这个参数很多,那如果像上面那样一个一个去获取参数,那岂不是要写疯!下面就来看看如何解决这种情况。

读取所有参数

方法一

既然bash shell通过位置可获取参数,那意味着如果我们知道参数的总个数就可以通过循环依次获取参数。那么如何获取参数总个数呢?

在bash shell中通过 $# 可获取参数总数。

示例:(循环获取参数)

#!/bin/bash
for (( index=0; index <= $#; index++ ))
do
echo ${!index}
done

以上示例,我们通过 $# 获取总参数个数。然后通过循环获取每个位置的参数。注意: 按照正常的理解,上面的 ${!index} 应该是 ${$index}才对, 对吧? 但是,由于${}内不能再写$符号,bash shell在这个地方是用了!符号,所以以上才写为了${!index}。

方法二

在bash shell中还可以通过 $* 和 $@ 来获取所有参数。但是这两者之间有着很大的区别:

$* 会将命令行上提供的所有参数当作一个单词保存, 我们得到的值也就相当于是个字符串整体。

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

可能文字看起来描述的不太清楚,那么还是通过示例来看二者的区别吧:

#!/bin/bash
#testinput.sh
var1=$*
var2=$@
echo "var1: $var1"
echo "var2: $var2"
countvar1=1
countvar2=1
for param in "$*"
do
echo "first loop param$countvar1: $param"
countvar1=$[ $countvar1 + 1 ]
done
echo "countvar1: $countvar1" for param in "$@"
do
echo "second param$countvar2: $param"
countvar2=$[ $countvar2 + 1 ]
done
echo "countvar2: $countvar2"

执行上面的示例:

./testinput.sh 12 34 56 78

上面示例的输出结果为:

var1: 12 34 56 78

var2: 12 34 56 78

param1: 12 34 56 78

countvar1: 2

param1: 12

param2: 34

param3: 56

param4: 78

countvar2: 5

通过上面的结果可见,直接输出看起来二者结果一样,但是通过for循环就可看出二者的区别了。上一篇文章我们讲到for循环会通过IFS定义的值进行分割,因此默认情况下,如果我们上面在for循环处不加引号,那么根据IFS中所定义的空格分割,最终也会导致看不出二者区别。

获得用户输入

单个输入

有时候,我们在shell执行过程中获取用户的输入,以此与用户进行交互。这是通过read命令来实现的。下面就来看看其用法:

示例一:

#!/bin/bash
echo -n "yes or no(y/n)?"
read choice
echo "your choice: $choice"

运行以上示例,首先会输出”yes or no(y/n)?“, 然后会等待用户输入(-n参数表示不换行,因此会在本行等待用户输入),当用户输入后,会把用户输入的值赋值给choice变量, 然后最终输出 “your choice: (你输入的内容)”。

事实上,我们可以不指定read后面的变量名,如果我们不指定, read命令会将它收到的任何数据都放进特殊环境变量REPLY中。如下:

示例二:

#!/bin/bash
echo -n "yes or no(y/n)?"
read
echo "your choice: $REPLY"

以上示例与示例一是等价的。

有时候,我们需要用户输入多个参数,当然,shell是支持一次接受多个参数输入的。

多个输入

示例三:

#!/bin/bash
read -p "what's your name?" first last
echo first: $first
echo last: $last

以上示例首先输出“what's your name?”, 然后在本行等待用户输入(此处用read -p实现以上示例的echo -n + read命令的不换行效果),输入的参数以空格分隔,shell会把输入的值依次赋值给first和last两个变量。如果输入的值过多,假如我输入了3个值,那么shell会把剩下的值都赋值给最后一个变量(即第二三两个的值都会赋值给last变量)。

细想一下,有个问题,假如用户一直不输入,怎么办?一直等待?

超时设置

我们可以通过read -t 来指定超时时间(单位为秒),如果用户在指定时间内没输入,那么read命令就会返回一个非0的状态码。

示例四:

#/bin/bash
if read -t 5 -p "Please enter your name: " name
then
echo "Hello $name"
else
echo "Sorry, timeout! "
fi

运行以上示例,如果超过5秒没输入,那么就会执行else里面的。

小结

本篇简单的介绍了shell的输入参数以及接收用户输入。大家可以举一反三,结合之前所学的基础知识,可以写一些小的脚本应用了。

我的独立博客: javafan.cn

shell编程其实真的很简单(五)的更多相关文章

  1. shell编程其实真的很简单(一)

    如今,不会Linux的程序员都不意思说自己是程序员,而不会shell编程就不能说自己会Linux.说起来似乎shell编程很屌啊,然而不用担心,其实shell编程真的很简单. 背景 什么是shell编 ...

  2. shell编程其实真的很简单(四)

    上篇我们学习了shell中条件选择语句的用法.接下来本篇就来学习循环语句.在shell中,循环是通过for, while, until命令来实现的.下面就分别来看看吧. for for循环有两种形式: ...

  3. shell编程其实真的很简单(二)

    上篇我们学会了如何使用及定义变量.按照尿性,一般接下来就该学基本数据类型的运算了. 没错,本篇就仍是这么俗套的来讲讲这无聊但又必学的基本数据类型的运算了. 基本数据类型运算 操作符 符号 语义 描述 ...

  4. shell编程其实真的很简单(三)

    通过前两篇文章,我们掌握了shell的一些基本写法和变量的使用,以及基本数据类型的运算.那么,本次就将要学习shell的结构化命令了,也就是我们其它编程语言中的条件选择语句及循环语句. 不过,在学习s ...

  5. HTTP真的很简单

    原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...

  6. HTTP真的很简单(转)

    原文:HTTP Made Really Easy因为我本身网络基础就很差,所以看到这篇文章一方面是学习网络知识,另一方面为了锻炼我蹩脚的英语水平,文中如有错误,欢迎浏览指正! 前言 在看这篇文章的时候 ...

  7. zabbix真的很简单 (安装篇)

    系统环境: Centos 6.4 一直觉得 zabbix 很简单,但是还是有好多人看了好多文档都搞不明白怎么用,我从2013年使用到现在也小有心得,如果时间允许,很高兴与大家一起分享我在使用过程中的一 ...

  8. 如果你这么去理解HashMap就会发现它真的很简单

    Java中的HashMap相信大家都不陌生,也是大家编程时最常用的数据结构之一,各种面试题更是恨不得掘地三尺的去问HashMap.HashTable.ConcurrentHashMap,无论面试题多么 ...

  9. 渗透测试实验(i春秋 真的很简单)

    首先利用给的提示: 所以用户名是 ichunqiu 密码是adab29e084ff095ce3eb 可以确定一般密码都是md5的,但是这个20位 应该去掉ada b29e084ff095ce3e才是正 ...

随机推荐

  1. CodeForces 652A Gabriel and Caterpillar

    简单模拟. #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> ...

  2. iOS开发——二级列表

    原理很简单,一级菜单放在viewForHeaderInSection里面,加一个点击事件,然后判断它的二级菜单(cell)显不显示. 直接上代码吧! // //  HeheTableViewContr ...

  3. ios 设置屏幕方向的两种方法

    第一种:通过人为的办法改变view.transform的属性. 具体办法: view.transform一般是View的旋转,拉伸移动等属性,类似view.layer.transform,区别在于Vi ...

  4. 阿里开源Mysql分布式中间件:Cobar

    目前在从事数据库中间件的开发和维护工作,我们使用的数据库中间件就是由cobar改造而来,所以对于cobar的一些说明一看就明白了: 下面是看到的一个很不错的分析文档 这里整理了下方便自己学习使用. C ...

  5. radioButton添加试题选项webview(二)

    由于项目里radioGroup里,4个选项里加载的是webview,而不是radiobutton本身自己可设置的text类型,并且每个webview都需要和radiobutton对齐,所以这个布局有点 ...

  6. diskpart修改盘符

    开机运行一批处理.内容如下:diskpart /s c:\disk.txt c:\disk.txt内容如下:select disk 1            #1选择第二个硬盘 0选择第二个硬盘sel ...

  7. iOS 之 网络 NSURLSession

    NSURLSession相比NSURLConnection功能更强大,是更上层的网络封装.相比而言,普通应用场景下NSURLSession没有什么优势,但是,在程序切换到后台的情况下,NSURLSes ...

  8. Python常见数据结构整理

    Python中常见的数据结构可以统称为容器(container).序列(如列表和元组).映射(如字典)以及集合(set)是三类主要的容器. 一.序列(列表.元组和字符串) 序列中的每个元素都有自己的编 ...

  9. linux下简单限制网卡速度

    Linux下限制网卡的带宽,可用来模拟服务器带宽耗尽,从而测试服务器在此时的访问效果. 1.安装iproute yum -y install iproute 2.限制eth0网卡的带宽为50kbit: ...

  10. Linux系统迁移

    文章来源http://blog.csdn.net/gt945/article/details/12253585 sudo rsync -aAXvP --exclude-from=exclude.txt ...