变量 含义

$0:shell脚本的名字;

$1 位置参数 #1

$2 - $9 位置参数 #2 - #9

${10} 位置参数 #10

"$*" :代表"$1c$2c$3 ..."形式保存所有参数,c为分隔符,默认为空格。如"$1 $2 $3 ..."

$@:代表"$1"、"$2"、“$3”...,将各个参数分别加双引号返回。

$# :传入的参数个数

$?:代表上一个命令执行后的退出状态,返回值0表成功。其他任何值表明有错误。

shell中用"exit"命令退出,参数n表示带返回值n退出。没有n则返回最后一个命令执行的后的状态,在shell被终止前,将执行exit的陷阱,

这个n值存放在$?中,一般来说, exit 0表示成功,exit 1表示失败。echo $?去查看返回的结果。

其他不常用的:

$$ 脚本运行的进程ID(PID)

$- 传递到脚本中的标志(和使用set相同效果) ,显示shell使用的当前选项

$_ 之前命令的最后一个参数

$!:运行在后台的最后一个作业的进程ID(PID),也就是上一个命令的PID

为了结合实例方便理解,下面给出详细的文章:

以下大部分引自网络:

0.引言

写程序常要处理命令行参数,在Bash下的命令行处理方式:

选项与参数:

如下一个命令行:

./test.sh -f config.conf -v --prefix=/home

我们称-f为选项,它需要一个参数,即config.conf, -v 也是一个选项,但它不需要参数。

--prefix我们称之为一个长选项,即选项本身多于一个字符,它也需要一个参数,用等号连接,当然等号不是必须的,/home可以直接写在--prefix后面,即--prefix/home,更多的限制后面具体会讲到。

在bash中,可以用以下三种方式来处理命令行参数,每种方式都有自己的应用场景。

* 手工处理方式

* getopts

* getopt

下面我们依次讨论这三种处理方式。

1. 手工处理方式

在手工处理方式中,首先要知道几个变量,还是以上面的命令行为例:

* $0 : ./test.sh,即命令本身,相当于C/C++中的argv[0]

* $1 : -f,第一个参数.

* $2 : config.conf

* $3, $4 ... :类推。

* $# 参数的个数,不包括命令本身,上例中$#为4.

* $@ :参数本身的列表,也不包括命令本身,如上例为 -f config.conf -v --prefix=/home

* $* :和$@相同,但"$*" 和 "$@"(加引号)并不同,"$*"将所有的参数解释成一个字符串,而"$@"是一个参数数组。如下例所示:

1 #!/bin/bash

2

3 for arg in "$*"

4 do

5 echo $arg

6 done

7

8 for arg in "$@"

9 do

10 echo $arg

11 done

12

执行./test.sh -f config.conf -n 10 会打印:

-f config.conf -n 10 #这是"$*"的输出

#以下为$@的输出:

-f

config.conf

-n

10

所以,手工处理的方式即对这些变量的处理。因为手工处理高度依赖于你在命令行上所传参数的位置,所以一般都只用来处理较简单的参数。如

./test.sh 10

而很少使用./test -n 10这种带选项的方式。 典型用法为:

#!/bin/bash

if [ x$1 != x ]

then

#...有参数

else

then

#...没有参数

fi

为什么要使用 x$1 != x 这种方式来比较呢?想像一下这种方式比较:

if [ -n $1 ] #$1不为空

但如果用户不传参数的时候,$1为空,这时 就会变成 [ -n ] ,所以需要加一个辅助字符串来进行比较。

手工处理方式能满足大多数的简单需求,配合shift使用也能构造出强大的功能,但在要处理复杂选项的时候建议用下面的两种方法。

2. getopts/getopt

处理命令行参数是一个相似而又复杂的事情,为此,C提供了getopt/getopt_long等函数,

C++的boost提供了Options库,在shell中,处理此事的是getopts和getopt.

getopts和getopt功能相似但又不完全相同,其中getopt是独立的可执行文件,而getopts是由Bash内置的。

先来看看参数传递的典型用法:

* ./test.sh -a -b -c : 短选项,各选项不需参数

* ./test.sh -abc : 短选项,和上一种方法的效果一样,只是将所有的选项写在一起。

* ./test.sh -a args -b -c :短选项,其中-a需要参数,而-b -c不需参数。

* ./test.sh --a-long=args --b-long :长选项

我们先来看getopts,它不支持长选项。

使用getopts非常简单:

代码

#test.sh

#!/bin/bash

while getopts "a:bc" arg #选项后面的冒号表示该选项需要参数

do

case $arg in

a)

echo "a's arg:$OPTARG" #参数存在$OPTARG中

;;

b)

echo "b"

;;

c)

echo "c"

;;

?) #当有不认识的选项的时候arg为?

echo "unkonw argument"

exit 1

;;

esac

done

现在就可以使用:

./test.sh -a arg -b -c



./test.sh -a arg -bc

来加载了。

应该说绝大多数脚本使用该函数就可以了,如果需要支持长选项以及可选参数,那么就需要使用getopt.

下面是getopt自带的一个例子:

#!/bin/bash

# A small example program for using the new getopt(1) program.

# This program will only work with bash(1)

# An similar program using the tcsh(1) script language can be found

# as parse.tcsh

# Example input and output (from the bash prompt):

# ./parse.bash -a par1 'another arg' --c-long 'wow!*/?' -cmore -b " very long "

# Option a

# Option c, no argument

# Option c, argument `more'

# Option b, argument ` very long '

# Remaining arguments:

# --> `par1'

# --> `another arg'

# --> `wow!*/?'

# Note that we use `"$@"' to let each command-line parameter expand to a

# separate word. The quotes around `$@' are essential!

# We need TEMP as the `eval set --' would nuke the return value of getopt.

#-o表示短选项,两个冒号表示该选项有一个可选参数,可选参数必须紧贴选项

#如-carg 而不能是-c arg

#--long表示长选项

#"$@"在上面解释过

# -n:出错时的信息

# -- :举一个例子比较好理解:

#我们要创建一个名字为 "-f"的目录你会怎么办?

# mkdir -f #不成功,因为-f会被mkdir当作选项来解析,这时就可以使用

# mkdir -- -f 这样-f就不会被作为选项。

TEMP=`getopt -o ab:c:: --long a-long,b-long:,c-long:: /

-n 'example.bash' -- "$@"`

if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi

# Note the quotes around `$TEMP': they are essential!

#set 会重新排列参数的顺序,也就是改变$1,$2...$n的值,这些值在getopt中重新排列过了

eval set -- "$TEMP"

#经过getopt的处理,下面处理具体选项。

while true ; do

case "$1" in

-a|--a-long) echo "Option a" ; shift ;;

-b|--b-long) echo "Option b, argument /`$2'" ; shift 2 ;;

-c|--c-long)

# c has an optional argument. As we are in quoted mode,

# an empty parameter will be generated if its optional

# argument is not found.

case "$2" in

"") echo "Option c, no argument"; shift 2 ;;

*) echo "Option c, argument /`$2'" ; shift 2 ;;

esac ;;

--) shift ; break ;;

*) echo "Internal error!" ; exit 1 ;;

esac

done

echo "Remaining arguments:"

for arg do

echo '--> '"/`$arg'" ;

done

比如我们使用

./test -a -b arg arg1 -c

你可以看到,命令行中多了个arg1参数,在经过getopt和set之后,命令行会变为:

-a -b arg -c -- arg1

$1指向-a,$2指向-b,$3指向arg,$4指向-c,$5指向--,而多出的arg1则被放到了最后。

Shell script 传参数处理(默认变量)的更多相关文章

  1. shell script针对参数已经有配置好变量名称

    /path/to/scriptname opt1 opt2 opt3 opt4 $ $ $ $ $ 这样够清楚了吧?运行的脚本档名为 $0 这个变量,第一个接的参数就是 $1 啊- 所以,只要我们在 ...

  2. [2019.03.20]Linux Shell 执行传参数和expr

    前不久入职实习生,现在在帮着组里面dalao们跑Case,时不时要上去收一下有木有Dump,每次敲命令太烦人于是逼着自己学写Shell脚本.一开始真的是很痛苦啊,也没能搞到书,只能凭网上半真半假的消息 ...

  3. shell命令传参数(参数长度不定)

    脚本 sudo echo "[mysqlMaster<$1>]" >> /home/admin/hostrecord count= ];do >> ...

  4. shell 文件传 参数

    n cross-platform, lowest-common-denominator sh you use: #!/bin/sh value=`cat config.txt` echo " ...

  5. python中函数的参数:必传参数(位置参数)、默认值参数、参数组传参、关键字传参

    1.必传参数也叫做位置参数,因为必填,也必须对应位置 2.默认值参数如上图的word 3.参数组参数:传进去的是0个.或多个value的形式,,,和位置参数有点像,只传value值,但是没有限制个数 ...

  6. 第13章 学习shell script

    由于博客园中dollar符号有别的意义,所以文中的dollar符号使用¥表示 第一个script [root@localhost script]# cat -n sh01.sh #!/bin/bash ...

  7. shell及脚本4——shell script

    一.格式 1.1 开头 必须以 "# !/bin/bash"  开头,告诉系统这是一个bash shell脚本.注意#与!中间有空格. 二.语法 2.1 数值运算 可以用decla ...

  8. shell脚步传参

    linux系统除了提供位置参数还提供内置参数,内置参数如下: $# ----传递给程序的总的参数数目 $? ----上一个代码或者shell程序在shell中退出的情况,如果正常退出则返回0,反之为非 ...

  9. shell编程 Shell script 的默认变量($0, $1...)

    Shell script 的默认变量($0, $1...) 我们知道指令可以带有选项与参数,例如 ls -la 可以察看包含隐藏文件的所有属性与权限.那么 shell script 能不能在脚本文件名 ...

随机推荐

  1. J-Link固件烧录以及使用J-Flash向arm硬件板下载固件程序

    这篇文章的最初版本是在15年写的https://blog.csdn.net/u010592722/article/details/45575663,后来又遇到了一些新问题,故更新在了这里. 一.始于安 ...

  2. 安卓高级 特效动画ExplosionField和 SmoothTransition

    本教程所有图片为github上的所无法正常访问请科学上网 SmoothTransition 展示效果 github:源码地址 使用方法 你能通过一行代码使用上面所有的动画 @Override prot ...

  3. 拾遗与填坑《深度探索C++对象模型》3.3节

    <深度探索C++对象模型>是一本好书,该书作者也是<C++ Primer>的作者,一位绝对的C++大师.诚然该书中也有多多少少的错误一直为人所诟病,但这仍然不妨碍称其为一本好书 ...

  4. Device Mapper 代码分析

    Device Mapper(DM)是Linux 2.6全面引入的块设备新构架,通过DM可以灵活地管理系统中所有的真实或虚拟的块设备. DM以块设备的形式注册到Linux内核中,凡是挂载(或者说&quo ...

  5. chromium出现输入密码解锁登录密钥环

    chromium出现输入密码解锁登录密钥环 在ubuntu 16.04上安装了Chromium出现对话框,如下所示: 因为密码框截图困难,这个是网上图片. 点取消就可以使用,但是每次都这样很烦,百度后 ...

  6. 无需密码通过scp命令+key的方式实现文件传输

    如果觉得scp每次都要输入密码很麻烦, 那么这是解决方案.假设你平时在windows上开发,用户名是xiang, 你有一台Ubuntu服务器wdksw.com, 用户名是root.现在你准备上传一些文 ...

  7. TextView的升级版———AutoCompleteTextView

    TextView的升级版---AutoCompleteTextView AutoCompleteTextView顾名知义,可以自动提示的TextView,还可以提示错误信息. 这里介绍基本的使用,能够 ...

  8. [tornado]websocket 最简单demo

    想法 前两天想看看django 长轮询或者是websocket的方案,发现都不太好使. tornado很适合做这个工作,于是找了些资料,参照了做了个最简单demo,以便备用. 具体的概念就不说了,to ...

  9. JDBC编程-事务编程(四)

    事务的概念 事务的概念在我看来是指的是一组sql序列,这个序列是一块执行的单位,要么全部执行,要不全部执行,这样可以很好的对数据库进行并发控制. 因为数据库是多个用户都可以同时操作的,如果多个用户同时 ...

  10. Android开发学习之路--异步消息Handler,Message,Looper和AsyncTask之初体验

    在简易音乐播放器中,用了Handler,也没有过多地去研究学习,这里再学习下android下的异步消息处理机制.这里用了Handler主要是在线程中不能更新UI,而需要通过Handler才可以.关于异 ...