• Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数


    变量名只能包含数字、字母和下划线,因为某些包含其他字符的变量有特殊含义,这样的变量被称为特殊变量。

    例如,$ 表示当前Shell进程的ID,即pid,看下面的代码:

    1. $echo $$

    运行结果

    29949
    特殊变量列表
    变量含义
    $0 当前脚本的文件名
    $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。
    $# 传递给脚本或函数的参数个数。
    $* 传递给脚本或函数的所有参数。
    $@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同,下面将会讲到。
    $? 上个命令的退出状态,或函数的返回值。
    $$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

    命令行参数

    运行脚本时传递给脚本的参数称为命令行参数。命令行参数用 $n 表示,例如,$1 表示第一个参数,$2 表示第二个参数,依次类推。

    请看下面的脚本:

    1. #!/bin/bash
    2. echo "File Name: $0"
    3. echo "First Parameter : $1"
    4. echo "First Parameter : $2"
    5. echo "Quoted Values: $@"
    6. echo "Quoted Values: $*"
    7. echo "Total Number of Parameters : $#"

    运行结果:

    $./test.sh Zara Ali
    File Name : ./test.sh
    First Parameter : Zara
    Second Parameter : Ali
    Quoted Values: Zara Ali
    Quoted Values: Zara Ali
    Total Number of Parameters : 2

    $* 和 $@ 的区别

    $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。

    但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。

    下面的例子可以清楚的看到 $* 和 $@ 的区别:

    1. #!/bin/bash
    2. echo "$*=" $*
    3. echo ""$*"=" "$*"
    4. echo "$@=" $@
    5. echo ""$@"=" "$@"
    6. echo "print each param from $*"
    7. for var in $*
    8. do
    9. echo "$var"
    10. done
    11. echo "print each param from $@"
    12. for var in $@
    13. do
    14. echo "$var"
    15. done
    16. echo "print each param from "$*""
    17. for var in "$*"
    18. do
    19. echo "$var"
    20. done
    21. echo "print each param from "$@""
    22. for var in "$@"
    23. do
    24. echo "$var"
    25. done

    执行 ./test.sh "a" "b" "c" "d",看到下面的结果:

    $*=  a b c d
    "$*"= a b c d
    $@=  a b c d
    "$@"= a b c d
    print each param from $*
    a
    b
    c
    d
    print each param from $@
    a
    b
    c
    d
    print each param from "$*"
    a b c d
    print each param from "$@"
    a
    b
    c
    d

    退出状态

    $? 可以获取上一个命令的退出状态。所谓退出状态,就是上一个命令执行后的返回结果。

    退出状态是一个数字,一般情况下,大部分命令执行成功会返回 0,失败返回 1。

    不过,也有一些命令返回其他值,表示不同类型的错误。

    下面例子中,命令成功执行:

    $./test.sh Zara Ali
    File Name : ./test.sh
    First Parameter : Zara
    Second Parameter : Ali
    Quoted Values: Zara Ali
    Quoted Values: Zara Ali
    Total Number of Parameters : 2
    $echo $?
    0
    $


    $? 也可以表示函数的返回值

    1 shell变量基础
    shell 变量是一种很“弱”的变量,默认情况下,一个变量保存一个串,shell不关心这个串是什么含义。所以若要进行数学运算,必须使用一些命令例如let、 declare、expr、双括号等。shell变量可分为两类:局部变量和环境变量。局部变量只在创建它们的shell中可用。而环境变量则可以在创建 它们的shell及其派生出来的任意子进程中使用。有些变量是用户创建的,其他的则是专用shell变量。变量名必须以字母或下划线字符开头。其余的字符 可以是字母、数字(0~9)或下划线字符。任何其他的字符都标志着变量名的终止。名字是大小写敏感的。给变量赋值时,等号周围不能有任何空白符。为了给变 量赋空值,可以在等号后跟一个换行符。用set命令可以查看所有的变量,unset var命令可以清除变量var,var相当于没有定义过。readonly var可以把var变为只读变量,定义之后不能对var进行任何更改。对shell变量的引用方式很多,用这些方式可以方便的获取shell变量的值,变 量值的长度,变量的一个字串,变量被部分替换后的值等等。shell变量常见引用方式如下:

    2 环境变量
    环境变量的定义方法如下:
    var=value
    export var
    shell在初始化的时候会在执行profile等初始化脚本,脚本中定义了一些环境变量,这些变量会在创建子进程时传递给子进程。
    用env命令可以查看当前的环境变量。常用的系统环境变量如下:
    _(下划线) 上一条命令的最后一个参数
    BASH 展开为调用bash实例时使用的全路径名
    CDPATH cd命令的搜索路径。它是以冒号分隔的目录列表,shell通过它来搜索cd命令指定的目标目录。例如.:~:/usr
    EDITOR 内置编辑器emacs、gmacs或vi的路径名
    ENV 每一个新的bash shell(包括脚本)启动时执行的环境文件。通常赋予这个变量的文件名是.bashrc。
    EUID 展开为在shell启动时被初始化的当前用户的有效ID
    GROUPS 当前用户所属的组
    HISTFILE 指定保存命令行历史的文件。默认值是~/.bash_history。如果被复位,交互式shell退出时将不保存命令行历史
    HISTSIZE 记录在命令行历史文件中的命令数。默认是500
    HOME 主目录。未指定目录时,cd命令将转向该目录
    IFS 内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分
    LANG 用来为没有以LC_开头的变量明确选取的种类确定locale类
    OLDPWD 前一个工作目录
    PATH 命令搜索路径。一个由冒号分隔的目录列表,shell用它来搜索命令,一个普通值为 /usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin
    PPID 父进程的进程ID
    PS1 主提示符串,默认值是$
    PS2 次提示符串,默认值是>
    PS3 与select命令一起使用的选择提示符串,默认值是#?
    PS4 当开启追踪时使用的调试提示符串,默认值是+。追踪可以用set –x开启
    PWD 当前工作目录。由cd设置
    RANDOM 每次引用该变量,就产生一个随机整数。随机数序列可以通过给RANDOM赋值来初始化。如果RANDOM被复位,即使随后再设置,它也将失去特定的属性
    REPLY 当没有给read提供参数时设置
    SHELL 当调用shell时,它扫描环境变量以寻找该名字。shell给PATH、PS1、PS2、MAILCHECK和IFS设置默认值。HOME和MAIL由login(1)设置
    SHELLOPTS 包含一列开启的shell选项,比如braceexpand、hashall、monitor等
    UID 展开为当前用户的用户ID,在shell启动时初始化
    3 数值变量
    shell中默认把变量值当作字符串,例如:
    age=22
    age=${age}+1
    echo ${age}
    输出结果为22+1,而不是23,因为shell将其解释为字符串,而不是数学运算。
    可以用let命令使其进行数学运算,例如:
    let age=${age}+1
    也可以用declare把变量定义为整型。例如:
    declare -i age=22
    这里就用 -i 选项把age定义为整型的了。此后每次运算,都把age的右值识别为算术表达式或数字。
    4 数组
    在shell中可以使用数组,例如:
    array[0]=0
    array[1]=1
    array[2]=2
    则array就是一个数组,也可以这样给数组初始化:
    array=(0 1 2) // 元素之间以空格分隔
    可 以通过 ${array[$i]}来访问array中某个元素,${array[*]} 的返回值即数组的所有元素组成的串,${#array[*]} 的返回值即数组的元素个数,${array[*]:0:2} 返回第一个和第二个元素组成的串。0表示开始的位置,2表示要返回的元素个数,开始位置可以为0-2(0减去2)之类的,表示从倒数第二个元素开始。
    下面写个稍微复杂点的例子:

    复制代码
    1 #!/bin/bash
    2 for ((i=0; i<100; i++))
    3 do
    4 array[$i]=$i
    5 done
    6 for ((i=0; i<100; i++))
    7 do
    8 echo ${array[$i]}
    9 done
    复制代码

    如果要使用二维数组甚至三维数组该怎么实现呢,那就需要用eval命令来模拟数组的功能了。
    eval命令的作用是扫描命令两次再执行,如果不使用eval,只扫描一次,然后执行。看个例子:
    root@suse:~$ name=Barry
    root@suse:~$ $name=hello
    Barry=hello: command not found
    为 什么第二句给Barry变量赋值会出错呢?从报错信息可以发现shell并没有识别这是个赋值语句,而是把Barry=hello当作一个命令来执行,当 然会报错。为什么不能识别这是赋值语句呢?第一次扫描时,因为扫描到$符号,所以不能把这句当作赋值语句,赋值语句的左边总是一个变量名,而不应该是$开 头的。所以第一次扫描仅仅识别了$name变量,并做了替换,而并没有认识到赋值语句。
    如果使用eval $name=hello呢?
    root@suse:~$ name=Barry
    root@suse:~$ $name=hello
    Barry=hello: command not found
    root@suse:~$ eval $name=hello
    root@suse:~$ echo $Barry
    hello
    可见使用了eval之后,对 $name=hello 第一次扫描替换了$name,没有识别赋值语句,第二次扫描识别是赋值语句,然后执行。现在大约可以想到怎样用eval实现二维数组了。
    下面实现的二维数组每一行代表一个人的信息记录,包括姓名,年龄。

    复制代码
     1 for ((i=0; i<2; i++))
     2 do
     3 for ((j=0; j<2; j++))
     4 do 
     5 read man$i$j
     6 done
     7 done
     8 echo "next print:"
     9 for ((i=0; i<2; i++))
    10 do
    11 for ((j=0; j<2; j++))
    12 do 
    13 eval echo -n "$man$i$j:"
    14 done
    15 printf "
    "
    16 done
    复制代码

    5 特殊变量
    $0:当前脚本的文件名
    $num:num为从1开始的数字,$1是第一个参数,$2是第二个参数,${10}是第十个参数
    $#:传入脚本的参数的个数
    $*:所有的位置参数(作为单个字符串)
    $@:所有的位置参数(每个都作为独立的字符串)。
    $?:当前shell进程中,上一个命令的返回值,如果上一个命令成功执行则$?的值为0,否则为其他非零值,常用做if语句条件
    $$:当前shell进程的pid
    $!:后台运行的最后一个进程的pid
    $-:显示shell使用的当前选项
    $_:之前命令的最后一个参数

  • 相关阅读:
    两分钟彻底让你明白Android Activity生命周期(图文)!
    C++命名空间 namespace的作用和使用解析
    编译型语言、解释型语言、静态类型语言、动态类型语言概念与区别
    git 使用详解(8)-- tag打标签
    C#托管代码与C++非托管代码互相调用
    Qt属性表控件的使用 QtTreePropertyBrowser
    在VS2010上使用C#调用非托管C++生成的DLL文件(图文讲解)
    (二十二)访问者模式详解(伪动态双分派)
    (二十一)状态模式详解(DOTA版)
    (二十)职责链模式详解(都市异能版)
  • 原文地址:https://www.cnblogs.com/timssd/p/4614991.html
Copyright © 2020-2023  润新知