原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://twentyfour.blog.51cto.com/945260/521448

知识体系:

#使用命令行参数

#设置选项

#获取用户输入

有时编写的脚本需要能和运行脚本的人员进行交互,bash
shell提供了一些方法来从用户处获取数据,这些方法有如下三种:

1- 命令行参数(添加在命令后的参数)

2- 命令行选项(修改命令行为的单字符串)

3- 直接读取键盘输入

1、命令行参数
向shell脚本传递数据最基本的方式就是命令行参数,主要就是说通过一些特殊变量是的bash
shell自动把输入的参数赋值给变量才执行脚本。这些变量叫做位置参数,分别有$1为第一个参数、$2为第二个参数、$0为程序名称。。。

1.1、读取参数

如下看个例子就能理解这个位置参数的概念了:

[root@wzp ~]# chmod u+x 1.1test

[root@wzp ~]# cat 1.1test

#!/bin/bash

a=1

for (( b=1; b<=$1; b++ ))

do

a=$[ $a * $b ]

done

echo the factorial of $1 is $a

[root@wzp ~]# ./1.1test 5

the factorial of 5 is 120

[root@wzp ~]# ./1.1test 4

the factorial of 4 is 24
主要来看./xx后面附带的命令行参数,只有一个参数也即为第一个参数很明显赋值为$1,通过for循环计算出累乘结果,所以你输入的第一个参数值改变了,结果也就随着改变。

如果要输入更多的命令行参数,那么每个命令行参数必须使用空格分隔出来,下面看一个例子:
[root@wzp
~]# cat 1.1test

#!/bin/bash

total=$[ $1 * $2 ]

echo the first param is $1

echo the second param is $2

echo the total value is $total

[root@wzp ~]# ./1.1test 2 3

the first param is 2

the second param is 3

the total value is 6

[root@wzp ~]# ./1.1test 4 7

the first param is 4

the second param is 7

the total value is 28
如上脚本很容易理解,我们看到2/3和4/7都分别被赋值给$1和$2,这里就是通过命令行参数之间的空格分开实现的。当然,数值可以给赋值,对于文本字符串也是可以的,如果要将出现空格的连于一体的参数值可以通过单引号或者双引号括起来,这样bash
shell就将其视为一个参数值,先来看个例子:
[root@wzp
~]# cat 1.1test

#!/bin/bash

echo hello $1,glad to meet you.

[root@wzp ~]# ./1.1test 51cto gdin

hello 51cto,glad to meet you.

[root@wzp ~]# ./1.1test 'netease corporation'

hello netease corporation,glad to meet you.
对于脚本中没有附带$2变量则把gdin参数忽略了。

还有一点必须说明的:

如果脚本输入的命令参数多于9个,就必须使用大括号把变量括起来,如{10},来看个例子:
[root@wzp
~]# cat 1.1test

#!/bin/bash

total=$[ ${10} + ${11} ]

echo the tenth param is ${10}

echo the eleventh param is ${11}

echo the total is $total

[root@wzp ~]# ./1.1test 1 2 3 4 5 6 7 8 9 10 11

the tenth param is 10

the eleventh param is 11

the total is 21
对于这样的结果很好理解,只要注意下{10+}这个东东就行了!

1.2、读取程序名称

一开始我就在上面提到程序名称用$0即可表示,Ok,先看个例子:
[root@wzp
~]# chmod u+x 1.2test

[root@wzp ~]# cat 1.2test

#!/bin/bash

echo the name of the program is:$0

[root@wzp ~]# ./1.2test

the name of the program is:./1.2test

[root@wzp ~]# /root/1.2test

the name of the program is:/root/1.2test
很明显,得出的结果不是我们要的,我们只要输出1.2test这个结果。它所传递的变量$0的字符串是程序的完整路径,而不是名称,这里我们可以通过basename命令实现只返回程序名称,把脚本修改成如下:
[root@wzp
~]# cat 1.2test

#!/bin/bash

name=`basename $0`

echo the name of the program is:$name

[root@wzp ~]# ./1.2test

the name of the program is:1.2test

[root@wzp ~]# $HOME/1.2test

the name of the program is:1.2test
呵呵,这下通过basename实现我们要的结果,有点注意的是使用反单引号来给name赋值,否则命令无法生效!

通过基于使用脚本的名称可以实现执行不同功能,下面看个例子:
[root@wzp
~]# cp 1.2test 51cto

[root@wzp ~]# ln -s 1.2test netease

[root@wzp ~]# ls -l 1.2test 51cto netease

-rwxr--r-- 1 root root 179 02-13 11:21 1.2test

-rwxr--r-- 1 root root 179 02-13 11:22 51cto

lrwxrwxrwx 1 root root   7 02-13
11:22 netease -> 1.2test

[root@wzp ~]# cat 1.2test

#!/bin/bash

name=`basename $0`

if [ $name = "51cto" ]

then

echo $name is a great IT community

elif [ $name = "netease" ]

then

echo $name is a great internet-sp
corparation

fi

[root@wzp ~]# ./51cto

51cto is a great IT community

[root@wzp ~]# ./netease

netease is a great internet-sp corparation
上面的例子通过脚本名称实现了不同内容的输出,可知basename好用啦!

脚本是先判断basename,然后根据basename执行函数。

1.3、测试参数

在shell脚本中使用命令行参数要小心,如果执行脚本缺少必要的参数,则会出现报错信息,如下:
[root@wzp
~]# cat 1.1test

#!/bin/bash

total=$[ ${10} + ${11} ]

echo the tenth param is ${10}

echo the elevnth param is ${11}

echo the total is $total

[root@wzp ~]# ./1.1test

./1.1test: line 2: +  : syntax error: operand
expected (error token is " ")

the tenth param is

the elevnth param is

the total is
我们不输入任何命令行参数,则脚本无法执行。

所以,我们可以通过-n这个参数进行检测:
[root@wzp
~]# cat 1.2test

#!/bin/bash

if [ -n "$1" ]

then

echo $1 exists !

else

echo your inputting is wrong

fi

[root@wzp ~]# ./1.2test twentyfour

twentyfour exists !

[root@wzp ~]# ./1.2test

your inputting is wrong
由此可见,通过该方法是检测参数是否存在的好方法。

2、特殊的参数变量
在bash shell中有一些特殊的变量用户跟踪命令行参数。

2.1、参数计数

我们可以使用bash shell提供的特殊变量$#来检测执行脚本时所包含的命令行参数的个数,看如下例子:

[root@wzp ~]# cat 2.1test

#!/bin/bash

echo there were $# parameters supplied.

[root@wzp ~]# chmod u+x 2.1test

[root@wzp ~]# ./2.1test

there were 0 parameters supplied.

[root@wzp ~]# ./2.1test aa bb cc

there were 3 parameters supplied.
所以,$#是一个值得我们记住脑中的好变量!

2.2、获取所有参数

有时候需要获取命令行中的参数,并对它们进行迭代。这里主要通过两个变量来实现对命令行参数的迭代,分别是:

变量$*和变量$@

变量$*将所有参数视为一个单词

变量$@将分别对待每个参数
我们看个例子\(≧▽≦)/
[root@wzp
~]# chmod u+x 2.2test

[root@wzp ~]# cat 2.2test

#!/bin/bash

a=1

for param1 in "$*"

do

echo "\$* parameter #$a = $param1"

a=$[ $a+1 ]

done

b=1

for param2 in "$@"

do

echo "\$# parameter #$b = $param2"

b=$[ $b+1 ]

done

c=1

for param3 in "$#"

do

echo "the total counts = $param3"

c=$[ $c+1 ]

done

[root@wzp ~]# ./2.2test a b c d e f

$* parameter #1 = a b c d e f

$# parameter #1 = a

$# parameter #2 = b

$# parameter #3 = c

$# parameter #4 = d

$# parameter #5 = e

$# parameter #6 = f

the total counts = 6
通过一个for循环迭代特殊变量,充分体现出$*$@$#三个特殊变量用途!

3、移位
bash shell提供了一个工具叫shift命令,实现改变命令行参数的相对位置

默认将每个参数变量左移一位。即为,$3的值移动给变量$2($n+1->$n),而变量$1则被丢弃,当然,$0这个程序名称没变。下面看个例子:

[root@wzp ~]# cat 3test

#!/bin/bash

count=1

while [ -n "$1" ]

do

echo "parameter #$count = $1"

count=$[ $count + 1 ]

shift

done

[root@wzp ~]# chmod u+x 3test

[root@wzp ~]# ./3test 51cto emc linux rac

parameter #1 = 51cto

parameter #2 = emc

parameter #3 = linux

parameter #4 = rac
每测试一个参数,使用shift命令将参数移前一位,所以通过while循环即可是的每个参数都变成$1被循环下去显示出来。当然,我们可以指定shift的位数,而不是默认的一位。看如下例子:
[root@wzp
~]# cat 3test

#!/bin/bash

echo "the original parameter : $*"

shift 3

echo "the new shift parameter is : $1"

[root@wzp ~]# ./3test aa bb cc dd ee

the original parameter : aa bb cc dd ee

the new shift parameter is : dd
指定位数为3后,aa bb cc则被忽略了,直接把dd当成$1.

4、处理选项
选项是有破折号引导的单个字母,它更改命令的行为。如下罗列一些标准化选项:

**********************************************

选项                 
描述

-a            
实现所有对象

-c            
生成计数

-d            
指定目录

-e            
展开对象

-f            
指定读取数据的文件

-h            
显示命令的帮助信息

-i            
忽略大小写

-l            
生成长格式的输出

-n            
使用非交互式(批量)模式

-o            
指定一个输出文件来重定向输出

-q            
以quite模式退出

-r            
递归处理目录和文件

-s            
以silent模式执行

-v            
生成verbose模式

-x            
排除和拒绝

-y            
设置所有提问回答为yes

**********************************************

4.1、处理简单选项

先来看一个例子:
[root@wzp
~]# cat 4test

#!/bin/bash

while [ -n "$1" ]

do

case "$1" in

-a) echo "the -a option exists";;

-b) echo "the -b option exists";;

-c) echo "the -c option exists";;

*) echo "the '$1' is not an option ";;

esac

shift

done

[root@wzp ~]# ./4test -a -b -c -d -e

the -a option exists

the -b option exists

the -c option exists

the '-d' is not an option

the '-e' is not an option 
通过case语句循环判断各个选项,并且通过shift灵活移动选项变量。

4.2、从参数中分离选项

执行shell脚本经常会遇到使用选项又需要使用参数的情况。在linux中的标准方式是通过特殊字符码(--,双破折号)将二者分开,表示说当这个脚本程序发现双破折号后,就自动把剩余的命令行视为参数,而不再是选项了,如下看个例子:
[root@wzp
~]# cat 4test

#!/bin/bash

while [ -n "$1" ]

do

case "$1" in

-a) echo "the -a option exists";;

-b) echo "the -b option exists";;

-c) echo "the -c option exists";;

--) shift

break;;

*) echo "the '$1' is not an option ";;

esac

shift

done

count=1

for param in $@

do

echo "parameter #$count:$param"

count=$[ $count + 1 ]

done

[root@wzp ~]# ./4test -a -c -f -- -b test

the -a option exists

the -c option exists

the '-f' is not an option

parameter #1:-b

parameter #2:test
如上先通过while循环,把满足条件的选项显示出来,不满足条件的选项也显示出,并说明 is not an option
,当使用--把剩下的被脚本识别为参数的命令行则通过break跳出循环,并且在shift作用下置位成$1,然后在for循环下逐一显示出来,表示现实出来的即为参数,而非选项!

如上的脚本得仔细分析,不然很容易出错。

如果不通过双破折号隔离,如下的结果也是我们想象之中的:
[root@wzp
~]# ./4test -a -c -f -b test

the -a option exists

the -c option exists

the '-f' is not an option

the -b option exists

the 'test' is not an option 
完全是while循环的判断,没法跳出来执行for循环。

5、获取用户输入
有时在脚本执行过程中需要询问一个问题并等待执行脚本的人员应答,bash shell提供的read命令可以实现这一需求。

5.1、基本读取

read命令接受标准输入(键盘输入),如下示例:

[root@wzp ~]# chmod u+x 5.1test

[root@wzp ~]# cat 5.1test

#!/bin/bash

echo -n "please input your name:"

read name

echo "hello $name, welcome to IT website"

[root@wzp ~]# ./5.1test

please input your name:twentyfour

hello twentyfour, welcome to IT website
通过一个-n选项使得脚本执行输入不用换行显示。

如上通过echo显示结果,实际上可以直接通过read命令在-p选项下直接把输入的内容附加给后面指定的变量,如下例子,效果跟上面完全一样:
[root@wzp
~]# cat 5.1test

#!/bin/bash

read -p "please input your name:" name

echo "hello $name, welcome to IT website"

[root@wzp ~]# ./5.1test

please input your name:CCIE

hello CCIE, welcome to IT website
所以,我们更多可以采用这种方法。

如上的两个方法,我们都是把输入的值赋给了变量name,实际上我们可以不使用这个变量name。这么一来,read命令会把输入的命令赋给一个环境变量REPLY,先来看一个效果:
[root@wzp
~]# read

the content will be sent to \$REPLY

[root@wzp ~]# echo $REPLY

the content will be sent to $REPLY
我使用\把变量转义不被识别,在read命令下输入的内容将被缓存赋给环境变量$REPLY(这个是系统级别的,直接引用),这下再来看个例子:
[root@wzp
~]# cat 5.1test

#!/bin/bash

read -p "please input your name:"

echo "hello $REPLY, welcome to IT website"

[root@wzp ~]# ./5.1test

please input your name:IBM

hello IBM, welcome to IT website
很明显,这个例子跟如上的很接近,但是这个脚本没使用name变量,所以我输入的IBM被系统赋给了环境变量$REPLY。

5.2、计时
如上我们可以通过read命令实现交互性的操作,但是假如没有执行脚本的人员操作,脚本则无法自动运行下去。这个时候就可以使用-t选项指定一个计时器,表示等待时间段(单位为秒),如果超过指定的时间,read命令将返回一个非零退出状态,通过判断语句则使脚本可以自动跳过运行下去,我们先看一个例子:
[root@wzp
~]# chmod u+x 5.2test

[root@wzp ~]# cat 5.2test

#!/bin/bash

if read -t 5 -p "please input your name:"

then

echo "hello $REPLY, welcome to come back
here"

else

echo "sorry , you are too slow "

fi

[root@wzp ~]# ./5.2test

please input your name:twentyfour

hello twentyfour, welcome to come back here

[root@wzp ~]# ./5.2test

please input your name:sorry , you are too slow 
如上通过-t
5是的输入超过5秒则跳到else的判断结果,有点需要注意就是-p必须放置在-t的后面,否则报错!如上我没有任何输入,超过5秒,则脚本返回了sorry
, you are too slow的内容。

到这里还有一个挺经典的-n选项不得不提,除了如上输入时间计时,read还可以通过添加-n选项计数输入的字符。等输入的字符达到预定数目时就自动退出,这里借助case看一个例子:
[root@wzp
~]# cat 5.2test

#!/bin/bash

read -n1 -p "do you want to continue [Y/N]?"

case $REPLY in

Y | y) echo

echo "fine ,continue on ..";;

N | n) echo

echo "OK, goodbye...";;

esac

[root@wzp ~]# ./5.2test

do you want to continue [Y/N]?y

fine ,continue on ..

[root@wzp ~]# ./5.2test

do you want to continue [Y/N]?N

OK, goodbye...
如上-n后面是数字1,表示read命令接收到一个字符就退出,所以输入Y/N后不用回车就马上执行下去了。这里出现了两个echo,主要是使得结果换行显示,更显人性化。还有就是通过|符号识别大小写,也是人性化。

5.3、默读

有时候需要脚本用户进行输入,但输入的数据不显示出来,比如像password的输入。这里可以借用read命令下的-s选项,使得输入的数据颜色跟背景颜色一致,实现不显示数据的效果,看如下例子:
[root@wzp
~]# cat 5.3test

#!/bin/bash

read -s -p "please input your passwd:"

echo your passwd is $REPLY

[root@wzp ~]# chmod u+x 5.3test

[root@wzp ~]# ./5.3test

please input your passwd:your passwd is aaa

[root@wzp ~]# ./5.3test

please input your passwd:your passwd is 51cto
哈哈,这不失为一个非常棒的选项。还有,别以为数据颜色跟背景颜色一样后,你可以通过数据把数据选上而显示出来,linux命令行下输入的数据不占位,压根无法让你选上!

5.4、读取文件

read命令可以读取linux系统上存储的文件数据,每调用一次read命令,都会去读取一行文本(注意,是一行,不是整个文件内容),当read命令读完的文本内容将以非零状态退出。借用while命令看一个例子:
[root@wzp
~]# cat 5.4test

#!/bin/bash

count=1

cat 51cto.test | while read line

do

echo "LINE $count : $line"

count=$[ $count + 1 ]

done

[root@wzp ~]# cat 51cto.test

aaaaaaaaaa

bbbbbbbbbb

cccccccccc

[root@wzp ~]# ./5.4test

LINE 1 : aaaaaaaaaa

LINE 2 : bbbbbbbbbb

LINE 3 : cccccccccc
这里的51cto.test跟脚本文件放置同一个目录,当然最后就把要读取的文件以绝对路径写入脚本防止脚本读取不到。while命令使用read不断循环读取文件51cto.test中每一行,然后显示出来,直到read读取完后以非零状态退出而结束!



bash&nbsp;shell笔记4&nbsp;处理用…的更多相关文章

  1. bash&nbsp;shell笔记1&nbsp;脚本基础知识

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/505644 * ...

  2. bash&nbsp;shell笔记7&nbsp;创建函数

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/525126 知 ...

  3. bash&nbsp;shell笔记6&nbsp;脚本控制

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/522415 知 ...

  4. bash&nbsp;shell笔记5&nbsp;显示数据

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/521455 知 ...

  5. bash&nbsp;shell笔记3&nbsp;结构化命令二

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://twentyfour.blog.51cto.com/945260/513601 三 ...

  6. bash&nbsp;shell笔记2&nbsp;结构化命令

    二.使用结构化命令 知识内容: # 改变命令流 # 使用if-then逻辑 # 嵌套if-then # 测试条件 # 高级if-then功能 许多程序在脚本命令之间需要某些逻辑控制流,有些命令允许脚本 ...

  7. 单行bash、shell、perl命令

    主题:单行经典bash.shell.perl命令 作者:luomg 摘要: 会陆陆续的写自己工作中的常用有意思的命令,争取你能看完后就能搞定常见操作, 且尽量自少提供基本shell.perl的实现方式 ...

  8. 什么是shell? bash和shell有什么关系?

    什么是shell? bash和shell有什么关系? 博客分类: Linux   什么是Shell?      shell是你(用户)和Linux(或者更准确的说,是你和Linux内核)之间的接口程序 ...

  9. bash和shell的关系

    bash是borne again shell的缩写,它是shell的一种,Linux上默认采用的是bash. shell脚本中的方法带不带function的区别,例如: function foo () ...

随机推荐

  1. linux文件组、权限等

    文件所有者.所在组合其他组  --改变用户所在组    组和在oa系统中的组差不多,用户代表的好像是个体,组有点像角色的意思.不过权限的话并不是个体从组中获得,组仅仅是一个机制,进行部分文件控制与共享 ...

  2. javascript: 代码优化

    一.避免全局查找 在一个函数中会用到全局对象存储为局部变量来减少全局查找,因为访问局部变量的速度要比访问全局变量的速度更快些 function search() { //当我要使用当前页面地址和主机域 ...

  3. jQuery的width()、innerWidth()、outerWidth()方法

    width(): 不包括元素的外边距(margin).内边距(padding).边框(border)等部分的宽度. innerWidth(): 包括元素的内边距(padding),但不包括外边距(ma ...

  4. Django的model查询操作 与 查询性能优化

    Django的model查询操作 与 查询性能优化 1 如何 在做ORM查询时 查看SQl的执行情况 (1) 最底层的 django.db.connection 在 django shell 中使用 ...

  5. 用百度地图API打造方便自己使用的手机地图

    有钱人咱就不说了,因为偶是个穷银--因为穷,所以去年买的Huawei C8650+到现在还在上岗,对于没有钱买好的配置的手机的童鞋来说,类似于百度,谷歌,高德等商家的地图在自己的机器上跑起来确实是有点 ...

  6. Arcgis for Androd API开发系列教程(一)——地图显示与GPS定位

    序:最近呢,工作鸭梨不是怎么大,对于自己爱折腾的想法又冒出了水面,开始自己的android开发的学习之旅.但是呢,本人是做GIS的,所以呢,就打算从这方面入手看看,是不是有什么比较好玩的玩意呢,这才导 ...

  7. 行为驱动开发BDD概要

    BDD脱胎于TDD 行为驱动开发(Behavior-Driven Development,简称BDD),是在测试驱动开发(Test-Driven Development,TDD)基础上发展而来的一种软 ...

  8. win10 135/445端口关闭

    135端口关闭 见[在 Windows 下关闭135/139/445端口的图文方法] 445端口关闭 打开控制面板-->网络和共享中心-->更改适配器设置-->右键点击正在使用的网卡 ...

  9. bzoj 1864 三色二叉树

    Written with StackEdit. Description Input 仅有一行,不超过\(5*10^5\)个字符,表示一个二叉树序列. Output 输出文件也只有一行,包含两个数,依次 ...

  10. bzoj 1226 学校食堂Dining

    Written with StackEdit. Description 小\(F\) 的学校在城市的一个偏僻角落,所有学生都只好在学校吃饭.学校有一个食堂,虽然简陋,但食堂大厨总能做出让同学们满意的菜 ...