`
gelongmei
  • 浏览: 211313 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
文章分类
社区版块
存档分类
最新评论

参数处理-Shell传入参数的处理

 
阅读更多
参数处理-Shell传入参数的处理
1. $# 传递到脚本的参数个数
2. $* 以一个单字符串显示所有向脚本传递的参数。与位置变量不同,此选项参数可超过9个
3. $$ 脚本运行的当前进程ID号
4. $! 后台运行的最后一个进程的进程ID号
5. $@ 与$#相同,但是使用时加引号,并在引号中返回每个参数
6. $- 显示shell使用的当前选项,与set命令功能相同
7. $? 显示最后命令的退出状态。0表示没有错误,其他任何值表明有错误。
变量 含义
$0 脚本名字
$1 位置参数 #1
$2 - $9 位置参数 #2 - #9
${10} 位置参数 #10
$# 位置参数的个数
"$*" 所有的位置参数(作为单个字符串) *
"$@" 所有的位置参数(每个都作为独立的字符串)
${#*} 传递到脚本中的命令行参数的个数
${#@} 传递到脚本中的命令行参数的个数
$? 返回值
$$ 脚本的进程ID(PID)
$- 传递到脚本中的标志(使用set)
$_ 之前命令的最后一个参数
$! 运行在后台的最后一个作业的进程ID(PID)


       使用shell处理的时候对参数的处理是个基本模块,所以今天找到一篇简单易懂的文章来进行参考,作为以后shell参数处理的模板,推荐使用getOpts形式进行参数的处理。

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则被放到了最后。


3.总结
一般小脚本手工处理也许就够了,getopts能处理绝大多数的情况,getopt较复杂,功能也更强大。

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

shift其实很简单的,就是左移参数列表,shift一次就将最左边的参数$1移出去了,然后
原来的$2现在就变成了$1。

shift后面还可以带上一个数字,指明要移出多少个参数(默认只移出一个),比如说
shift 3 就是移出3个参数,之后原来的$4就变成了现在的$1。

eval就是先将后面的参数执行一遍,将必要的置换都做了,再来执行命令。举个例子:
MYFILE="cat myfile"
echo $MYFILE   # output: cat myfile
eval $MYFILE   # output: contents of myfile

再举个详细点儿的例子:
#!/bin/bash
# evalit
echo " Total number of arguments passed: $#"
echo " The process ID: $$"
echo " Last argument: " $(eval echo /$$#)
运行脚本:
$ ./evalit alpha bravo charlie
output as follows:
Total number of arguments passed: 3
The process ID: 780
Last argument:   charlie

读取文件
for i in `cat abc.txt`
do
echo $i
done
分享到:
评论

相关推荐

    UNIX实验---考勤程序--shell编程

    6. **脚本参数**:通过脚本参数可以传递外部数据,例如,启动考勤脚本时可以传入员工ID进行特定员工的考勤查询。 7. **函数**:定义和调用Shell函数可以使代码更模块化,便于复用和维护。 8. **错误处理和调试**:...

    UI-SHELL培训 0811.pptx

    UI_WriteSignal()函数根据传入的UI信号参数控制LED的行为,而UI_ProcessSignal()则根据接收到的信号来设定LED的显示动作。在不同应用程序状态处理器中调用UI_WriteSignal()以控制LED的状态。 3. **UI模块设计**: ...

    linux-shell的函数式编程工具

    这个函数会检查传入的参数是否为正数。 6. **函数式特性**: 虽然Shell不是纯粹的函数式语言,但有些特性接近。例如,你可以使用`mapfile`或`readarray`命令对数组进行操作,使用`$(command)`来执行命令并获取其...

    Linux-shell-ppt

    echo "没有传入参数" else echo "你传入了 $# 个参数" fi ``` **管道与重定向** 1. **管道**: `|`用于连接两个命令,将前一个命令的输出作为后一个命令的输入,如`ls | grep .txt`会列出所有.txt文件。 2. **...

    使用Linux-Shell转换PDF文件为图片

    Linux是一种广泛使用的开源操作系统,其内建的命令行工具(Shell)提供了强大的自动化处理能力。通过编写Shell脚本,我们可以执行一系列命令来批量处理PDF转图片的任务。 描述中提到的"封装好的jar包、sh文件及使用...

    北大青鸟教程---SHELL使用(ppt格式)

    位置参数变量是Shell脚本处理中特别重要的一部分,它们包含了运行脚本时传入的参数,从$0(脚本名)到$9。预定义变量,如`$#`(参数数量)、`$?`(命令执行状态)、`$$`(当前进程ID)和`$!`(后台运行的最后一个...

    java调用shell(包含有参数的调用)

    本文将详细解释Java如何调用Shell脚本,包括如何编写Shell脚本和在Java中如何传递参数。 首先,Shell脚本可以被看作是一系列Linux命令的集合,用于自动化执行多个命令。类似于Windows环境中的批处理文件,Shell脚本...

    Spark-shell批量命令执行脚本的方法

    接着,使用`exec`命令启动`$SPARK_HOME/bin/spark-shell`,并传入一系列参数,例如队列名称、应用程序名称、执行器核心数、内存大小以及配置项等。 在`!EOF`和`!EOF`之间的部分,我们可以写入Spark SQL或DataFrame...

    LINUX shell编程.doc

    在 Shell 编程中,可以像使用命令一样接受参数,并且可以区分位置参数和内部参数。 1. **位置参数**: - 通过 `$N` 获取,其中 `N` 是数字,从 1 开始。 - `$0` 代表脚本名称。 - `$1`, `$2`, ... 代表依次传入...

    习题07-Shell编程.pdf

    7. **处理多个参数**:当Shell脚本接收超过9个参数时,可以通过`shift`命令依次移动参数列表,以便访问后面的参数。 8. **设置执行权限的命令**:使用`chmod`命令加上参数`a+x`和文件名,例如`chmod a+x filename`...

    shell-文档资料

    2. **命令行参数**:如何在脚本中处理命令行传入的参数,以及`$0`、`$1`、`$#`等特殊变量的含义。 3. **输入/输出重定向**:在脚本中如何实现文件的读写,以及利用重定向实现数据流的控制。 4. **控制结构**:学会...

    精彩编程与编程技巧-Shell & Wait 的程序怎么写?...

    在编程领域中,Shell 和 Wait 是两个重要的概念,尤其是在处理进程管理和控制方面。通过结合使用 Shell 和 Wait,程序员可以有效地启动外部应用程序,并等待这些应用程序执行完毕。本文将详细介绍如何在 VB(Visual ...

    Shell – 通过参数名传递参数值

    在编写Linux Shell脚本时,通常我们会使用$1, $2等变量来接收命令行传入的参数。然而,这种方式存在一些不便之处,比如容易混淆参数顺序,不利于维护,以及在传递复杂参数时可能导致错误。为了解决这些问题,我们...

    java调用shell向DataX传递参数,where条件,包含特殊字符

    本问题聚焦于如何通过Java调用shell脚本,向DataX传递参数,特别是包含特殊字符的where条件。在实际操作中,这可能会涉及到字符串转义、参数安全传递以及shell命令的构建等多个技术点。 首先,我们需要理解DataX的...

    学习笔记-基础Shell编程

    - `$@`: 所有传入参数的列表,与 `$*` 类似但有所不同。 - `$?`: 上一个命令的退出状态码。 - `$$`: 当前进程的ID。 #### 五、Shell特殊变量示例 ```sh #!/bin/bash echo "FileName:$0" echo "FirstParameter:$...

    sh代码-shell-test01

    5. 脚本参数:脚本运行时可以通过位置参数访问传入的值,如`$1`、`$2`等。 为了更好地理解"sh代码-shell-test01",你需要打开`main.sh`和`README.txt`文件,仔细阅读并尝试运行脚本。同时,建议参考相关的Shell编程...

    linux操作系统之Shell编程.pdf

    - `$1`, `$2`, ...: 位置参数,用于接收脚本执行时传入的参数,$1是第一个参数,$2是第二个参数,以此类推。 2. **条件判断与流程控制**: - `[ -d "$1" ]`: 这是一个条件表达式,用于检查$1(即第一个位置参数)...

    LINUX与UNIX SHELL编程指南(16-28)

    通过$0到$9这些特殊变量,我们可以获取并处理脚本执行时传入的参数,这对于构建灵活、可配置的脚本至关重要。 “021-创建屏幕输出.PDF”和“022-创建屏幕输入.PDF”章节则涉及了I/O重定向,讲解如何将脚本的输出...

    java调用shell向DataX传参,带where条件,特殊字符

    在Java程序中调用Shell命令并传入带有特殊字符的参数时,会遇到一些挑战,因为Shell和DataX对特殊字符的处理方式可能不同。 首先,让我们理解Java如何调用Shell命令。在Java中,我们可以使用Runtime或者...

    Linux从入门到实战学习教程-8Shell基础.pptx

    在8.3章节中,你将学习如何在Shell脚本中接收和处理外部传入的参数。通常,脚本的第一条命令行参数用 `$1` 表示,第二条用 `$2`,依此类推。`$0`则代表脚本本身的名字。通过数组变量,还可以处理任意数量的参数。 ...

Global site tag (gtag.js) - Google Analytics