shell编程之变量

阅读更多

13.10.1   变量类型

变量可分为两类:局部变量和环境变量。局部变量只在创建它们的shell 中可用。而环境变量则可以在创建它们的shell 及其派生出来的任意子进程中使用。有些变量是用户创建的,其他的则是专用shell 变量。

13.10.2   命名惯例

变量名必须以字母或下划线字符开头。其余的字符可以是字母、数字(0~9) 或下划线字符。任何其他的字符都标志着变量名的终止。名字是大小写敏感的。给变量赋值时,等号周围不能有任何空白符。为了给变量赋空值,可以在等号后跟一个换行符。创建一个局部变量最简单的格式是给一个变量赋值,如以下格式所示。

格式

变量=

范例 13-49

name=Tommy

13.10.3   内置命令 declare

有两个内置命令可以用来创建变量,它们是declaretypeset ,其选项可以控制变量设置的方式。typeset 命令( 来自Korn shell) 的功能和declare 命令(bash) 完全一样。bash 文档中指出, 提供typeset 命令是为了和Korn shell 兼容。但是不建议使用它,而应使用内置命令declare” 12 。因此从这一点来说,我们将使用declare 命令( 即使我们使用typeset 也一样方便)

  不带任何参数时,declare 将列出所有已设置的变量。通常只读变量不能被重新赋值或复位。如果只读变量是用declare 创建的,那它们不可以被复位,但可以被重新赋值。整型变量也可以用declare 赋值。

格式

declare  变量=

范例13-50

declare name=Tommy

13-13  declare 选项

   

   

-a 13

将变量当作一个数组。即,分配元素

-f

列出函数的名称和定义

-F

只列出函数名

-i

将变量设为整型

-r

将变量设为只读

-x

将变量名输出到子 shell

13.10.4   局部变量和作用域

变量的作用域指变量在一个程序中的哪些地方可见。对于shell 来说,局部变量的作用域被限定在创建它们的shell 中。

给变量赋值时,等号前后不能有空白符。如果要给变量赋空值,可以在等号后跟一个换行符 14

变量前的美元符用来提取存储在变量里的值。

local 函数可以用来创建局部变量,但仅限于在函数内使用 ( 请参见 13.16.1 节, 定义函数 ”)

设置局部变量   局部变量可以通过简单地赋予它一个值或一个变量名来设置,或者如范例13-51 所示用declare 内置函数来设置。

范例13-51

1   $ round=world or declare round=world

    $ echo $round

    world

2   $ name="Peter Piper"

    $ echo $name

    Peter Piper

3   $ x=

    $ echo $x

4   $ file.bak="$HOME/junk"

    bash: file.bak=/home/jody/ellie/junk: not found

说明

1. 将局部变量 round 赋值为 world 。如果遇到变量名前面是个美元符的情况, shell 就执行变量替换。该命令显示变量 round 的值 ( 不要混淆提示符 ($) 和用来执行变量替换的 $ )

2. 局部变量 name 被赋值为 “Peter Piper” 。必须用引号来保护空白符,这样, shell 分析命令行时才不会将这个字符串看成是两个词。该命令显示变量 name 的值。

3. 这条命令没有给变量 x 赋值,因此 x 被赋值为空。结果显示一个空值,即空字符串。

4. 变量名中出现句点是非法的。变量名可以使用的字符只能是数字、字母和下划线。因此, shell 尝试将这个字符串作为一条命令来执行。

范例 13-52

1   $ echo $$

    1313

2   $ round=world

    $ echo $round

    world

3   $ bash            # Start a subshell

4   $ echo $$

    1326

5   $ echo $round

6   $ exit           # Exits this shell, returns to parent shell

7   $ echo $$

    1313

8   $ echo $round

    world

说明

1. 双美元符变量的值是当前 shell PID 。本例中这个 shell PID 1313

2. 将局部变量 round 赋值为字符串 world ,并打印该变量的值。

3. 另外启动一个 bash shell ,这个 shell 被称为子 shell(subshell child shell)

4. 当前这个 shell PID 1326 ,其父 shell PID 则是 1313

5. 局部变量 round 在这个 shell 中没有定义,因此打印了一个空行。

6. exit 命令终止当前 shell 并返回父 shell( 也可以按 Ctrl+D 组合键退出当前 shell)

7. 返回到父 shell 。显示它的 PID

8. 显示变量 round 的值。它是这个 shell 的局部变量。

设置只读变量   只读变量是不能被重新定义或复位的特殊变量。但是,如果使用了declare 函数,只读变量可以被重新定义,但不能被复位。

范例13-53

1   $ name=Tom

2   $ readonly name

    $ echo $name

    Tom

3   $ unset name

    bash: unset: name: cannot unset: readonly variable

4   $ name=Joe

    bash: name: readonly variable

5   $ declare -r city='Santa Clara'

6   $ unset city

    bash: unset: city: cannot unset: readonly variable

7   $ declare city='San Francisco'   # What happened here?

    $ echo $city

    San Francisco

说明

1. 局部变量 name 的值被设为 Tom

2. 将变量 name 设为只读。

3. 不能复位只读变量。

4. 不能重新定义只读变量。

5. declare 内置命令给只读变量 city 赋值 Santa Clara 。当所赋值串中包含空白符时必须用引号。

6. 因其是只读变量,所以不能被复位。

7. 当只读变量是由 declare 命令创建时,它不可以被复位,但可以被重新赋值。

13.10.5   环境变量

环境变量可用在创建它们的shell 和从该shell 派生的任意子shell 或进程中。它们通常被称为全局变量,以区别于局部变量。通常,环境变量应该大写。环境变量是已经用export 内置命令导出的变量。

变量被创建时所处的shell 被称为父shell 。如果父shell 又启动了一个shell ,这个新的shell 被称作子shell 。环境变量将传递给从创建它们的shell 里启动的任意子进程。它们从父亲传递给儿子再到孙子等,但是不可向其他方向传递。比如,一个子进程可以创建环境变量,但不能将它传回给它的父进程,只能传给它的子进程 15 。有一些环境变量,比如HOMELOGNAMEPATHSHELL ,在用户登录之前就已经被/bin/login 程序设置好了。通常,环境变量定义并保存在用户主目录下的.bash_profile 文件中。请参见表13-14 中列出的环境变量。

13-14  bash 环境变量

   

   

_( 下划线 )

上一条命令的最后一个参数

BASH

展开为调用 bash 实例时使用的全路径名

BASH_ENV

ENV 一样,但只可在 bash 2.0 或更高版本中设置 16

BASH_VERSINFO

使用 2.0 以上版本的 bash 时,展开为版本信息 16

BASH_VERSION

展开为当前 bash 实例的版本号

CDPATH

cd 命令的搜索路径。它是以冒号分隔的目录列表, shell 通过它来搜索 cd 命令指定的目标目录。例如 .:~:/usr

COLUMNS

设置该变量就给 shell 编辑模式和选择的命令定义了编辑窗口的宽度

DIRSTACK

2.0 或以上版本的 bash 中,代表目录栈的当前内容

EDITOR

内置编辑器 emacs gmacs vi 的路径名

ENV

每一个新的 bash shell( 包括脚本 ) 启动时执行的环境文件。通常赋予这个变量的文件名是 .bashrc ENV 的值被解释为路径名前, shell 先要对其进行参量扩展,命令替换和算术扩展

EUID

展开为在 shell 启动时被初始化的当前用户的有效 ID

FCEDIT

fc 命令的默认编辑器名

FIGNORE

执行文件名补全时可忽略的以冒号分隔的后缀列表。以 FIGNORE 中任一项为后缀的文件名被从匹配的文件名列表中排除。例如值为 .o:~

FORMAT

用来格式化在命令管道上的 time 关键字的输出

GLOBIGNORE

在文件名扩展 ( 称为 globbing) 时被忽略的文件列表

GROUPS

当前用户所属的组

HISTCMD

当前命令的历史编号或在历史清单中的序号。如果 HISTCMD 被复位,即使它随后就会重置,也将失去它的特殊属性

HISTCONTROL

如果设置了 ignorespace 值,以一个空格符开头的行将不会进入历史清单。如果设置了 ignoredups 值,那和前一个历史行匹配的行不会进入。值 ignoreboth 结合了这两个选项。如果被复位,或设置成除了上面所说的任意其他值时,所有被解释器所读的行都将保存到历史清单中

  HISTFILE

指定保存命令行历史的文件。默认值是 ~/.bash_history 。如果被复位,交互式 shell 退出时将不保存命令行历史

( 续表 )  

   

   

HISTFILESIZE

历史文件能包含的最大行数。当给这个变量赋值后,如果有必要,历史文件将被截尾,以使包含的行数不超过这个数。默认值是 500

HISTSIZE

记录在命令行历史文件中的命令数。默认是 500

HOME

主目录。未指定目录时, cd 命令将转向该目录

HOSTFILE

包含一个格式和 /etc/hosts 一样的文件的名称,当 shell 需要补全一个主机名时将读取该文件。文件可以交互式更改。下一次试图补全主机名时, bash 将新文件的内容添加到已经存在的数据库中

HOSTTYPE

自动设置正在运行 bash 的机器的类型。默认值是由系统决定的

IFS

内部字段分隔符,一般是空格符、制表符和换行符,用于由命令替换,循环结构中的表和读取的输入产生的词的字段划分

IGNOREEOF

控制 shell 接收到单独一个 EOF 字符作为输入时的行为。如果设置,它的值就是 shell 退出前在一个输入行的最前面键入的连续 EOF 字符的个数。如果变量存在但没有一个数字值,或没有值,那么默认值是 10 。如果它不存在, EOF 意味着给 shell 的输入的终止。它只在交互式 shell 中有效

INPUTRC

readline 启动文件的文件名,取代默认的 ~/.inputrc

LANG

用来为没有以 LC_ 开头的变量明确选取的种类确定 locale

LC_ALL

忽略 LANG 和任何其他 LC_ 变量的值

LC_COLLATE

确定对路径名扩展的结果进行排序时的整理顺序,以及匹配文件名与模式时的范围表达式,等价类和整理序列的行为

LC_MESSAGES

确定用于转换前面有一个 $ 的双引号串的 locale

LINENO

每次 shell 在一个脚本或函数中替换代表当前连续行号 ( 1 开始 ) 的十进制数时,都将引用该参数

MACHTYPE

包含一个描述正在运行 bash 的系统的串

MAIL

如果该参数被设置为某个邮件文件的名称,而 MAILPATH 未被设置,当邮件到达 MAIL 指定的文件时, shell 会通知用户

MAIL_WARNING

如果设置了该变量,当 bash 发现用于检查邮件的文件在上次检查后又被访问了,将打印消息 “The mail in [filename where mail is stored] has been read”

MAILCHECK

这个参数定义 shell 将隔多长时间 ( 以秒为单位 ) 检查一次由参数 MAILPATH MAILFILE 指定的文件,看看是否有邮件到达。默认值是 600 (10 分钟 ) 。如果将它设为 0 shell 每次输出主提示符之前都会去检查邮件

MAILPATH

由冒号分隔的文件名列表。如果设置了这个参数,只要有邮件到达任何一个由它指定的文件, shell 都会通知用户。每个文件名后面都可以跟一个百分号和一条消息,当文件修改时间发生变化时, shell 会显示这条消息。默认的消息是: You have mail

                                                ( 续表 )  

   

   

OLDPWD

前一个工作目录

OPTARG

上一个由 getopts 内置命令处理的选项参数的值

OPTERR

如果设置成 1 ,显示来自 getopts 内置命令的错误信息

OPTIND

下一个由 getopts 内置命令处理的参数的序号

OSTYPE

自动设置成一个串,该串描述正在运行 bash 的操作系统。默认值由系统决定

PATH

命令搜索路径。一个由冒号分隔的目录列表, shell 用它来搜索命令。默认路径由系统决定,并且由安装 bash 的管理员设置。一个普通值为

/usr/gnu/bin:/usr/local/bin:/usr/ucb:/usr/bin:

PIPESTATUS

一个数组,包含一列最近在管道执行的前台作业的进程退出状态值

PPID

父进程的进程 ID

PROMPT_COMMAND

赋给这个变量的命令将在主提示符显示前执行

PS1

主提示符串,默认值是 $

PS2

次提示符串,默认值是 >

PS3

select 命令一起使用的选择提示符串,默认值是 #?

PS4

当开启追踪时使用的调试提示符串,默认值是 + 。追踪可以用 set –x 开启

PWD

当前工作目录。由 cd 设置

RANDOM

每次引用该变量,就产生一个随机整数。随机数序列可以通过给 RANDOM 赋值来初始化。如果 RANDOM 被复位,即使随后再设置,它也将失去特定的属性

REPLY

当没有给 read 提供参数时设置

SECONDS

每次 SECONDS 被引用,将返回调用 shell 以来的秒数。如果给 SECONDS 赋一个值,以后引用返回的值将是赋值以来的秒数加上所赋的值。如果 SECONDS 被复位,即使随后再设置,它也将失去特定的属性

SHELL

当调用 shell 时,它扫描环境变量以寻找该名字。 shell PATH PS1 PS2 MAILCHECK IFS 设置默认值。 HOME MAIL login(1) 设置

SHELLOPTS

包含一列开启的 shell 选项,比如 braceexpand hashall monitor

SHLVL

每启动一个 bash 实例时将其加 1

TMOUT

设置退出前等待输入的秒数

UID

展开为当前用户的用户 ID ,在 shell 启动时初始化

设置环境变量 如果想设置环境变量,就要在给变量赋值之后或设置变量时使用export 命令( 参见表13-15) 。带-x 选项的declare 内置命令也可完成同样的功能( 输出变量时不要在变量名前面加$)

13-15  export 命令和它的选项

   

--

标志着选项末尾,余下的参数被视为变量

-f

- 值对被看作函数,而不是变量

-n

将一个全局 ( 导出 ) 变量转换成局部变量。之后该变量将不能被导出到子进程中

-p

显示所有的全局变量

格式

export 变量 =

变量 = 值; export 变量

declare –x 变量 =

范例 13-54

export NAME=john

PS1= '/d:/W:$USER> ' ; export PS1

declare -x TERM=sun

范例13-55

1   $ export TERM=sun    # or declare -x TERM=sun

2   $ NAME="John Smith"

    $ export NAME

    $ echo $NAME

    John Smith

3   $ echo $$

    319             # pid number for parent shell

4   $ bash         # Start a subshell

5   $ echo $$

    340             # pid number for new shell

6   $ echo $NAME

    John Smith

7   $ declare -x NAME="April Jenner"

    $ echo $NAME

    April Jenner

8   $ exit          # Exit the subshell and go back to parent shell

9   $ echo $$

    319             # pid number for parent shell

10  $ echo $NAME

    John Smith

说明

1. TERM 变量赋值 sun 。同时输出它。现在,由这个 shell 启动的所有进程都将继承这个变量。也可以用 declare –x 来完成同样的功能。

2. 定义并输出变量 NAME ,让它可以被当前 shell 启动的所有子 shell 使用。

3. 打印当前 shell PID 的值。

4. 启动一个新的 bash 。这个新 shell 称为子 shell 。原来那个 shell 称为父 shell

5. 新的 bash shell PID 保存在变量 $$ 中,回显这个变量的值。

6. 在父 shell 中设置的变量 NAME 导出给这个新 shell ,这条命令显示它的值。

7. 内置的 declare 函数是设置变量的另一种方式。用 -x 开关, declare 可以输出变量。该变量被重新设置为 April Jenner 。这个变化将输出到所有的子 shell ,但不会影响父 shell 。输出的变量不会向上传递给父 shell

8. 退出这个 bash shell

9. 再次显示父 shell PID

10. 变量NANE 的值还跟原来一样。从父shell 输出到子shell 时,变量保持它们的值不变。子shell 不可能改变父shell 的变量的值。

13.10.6   复位变量

只要不被设为只读,局部变量和环境变量都可以用unset 命令复位。

范例13-56

unset name; unset TERM

说明

unset 命令从 shell 存储器中删除变量。

13.10.7   显示变量值

echo 命令   内置echo 命令将它的参数显示到标准输出上。echo-e 选项,允许使用大量控制输出外观的转义序列。表13-16 列出了echo 选项和转义序列。

13-16  echo 选项和转义序列

   

   

-e

允许解释下面列出的转义序列

-E

禁止解释这些转义字符,即使在那些默认解释它们的系统上 (bash 2.x) 17

-n

删除输出结果中行尾的换行符

转义序列

\a

报警 ( )

\b

退格

\c

不带换行符打印一行

\f

换页

\n

换行

\r

回车

\t

制表符

\v

纵向制表符

\\

反斜杠

\nnn

ASCII 码是 nnn( 八进制 ) 的字符

当使用转义序列时,不要忘记用-e 开头。

范例 13-57

1   $ echo The username is $LOGNAME.

    The username is ellie.

2   $ echo -e "/t/tHello there/c"

                 Hello there$

3   $ echo -n "Hello there"

    Hello there$

说明

1. echo 命令将它的参数打印到屏幕上。 shell 会在执行 echo 命令之前先进行变量替换。

2. -e 选项的 echo 命令支持转义序列,和 C 编程语言类似。 $ shell 提示符。

3. -n 选项打开时,不带换行符打印一行。这个版本的 echo 不支持转义序列。

printf 命令  printf 18GNU 版本可以用来编排打印输出的格式。它以和C printf 函数相同的方式打印格式串。格式由一个串组成,它包含描述打印输出结果的格式指令。格式指令由带格式符(diouxXfeEgGcs)% 指定,%f 代表一个浮点数,%d 则代表一个( 十进制) 整数。

要得到printf 格式符的完整清单以及如何使用它们,可以在命令行键入:printf --help 。键入printf --version 就可以知道使用的printf 是什么版本。如果使用的是bash 2.x ,内置printf 命令所用的格式和/usr/bin 下的printf 可执行程序完全一样。

格式

printf 格式[ 参数…]

范例 13-58

printf "%10.2f%5d/n" 10.5  25

13-17  printf 命令的格式符

   

/"

双引号

/0NNN

一个八进制字符,这里 NNN 代表 0~3

//

反斜杠

/a

报警或蜂鸣

/b

退格

/c

不产生更多的输出

/f

换页

/n

换行

/r

回车

                                    ( 续表 )  

/t

水平制表符

/v

垂直制表符

/xNNN

十六进制字符,这里 NNN 1~3

%%

单个百分号

%b

字符串参数,也对 / 转义字符进行解释

范例 13-59

1   $ printf --version

    printf (GNU sh-utils) 1.16

2   $ type printf

    printf is a shell builtin

3   $ printf "The number is %.2f/n" 100

    The number is 100.00

4   $ printf "%-20s%-15s%10.2f/n" "Jody" "Savage" 28

    Jody                Savage              28.00

5   $ printf "|%-20s|%-15s|%10.2f|/n" "Jody" "Savage" 28

    Jody                |Savage          |    28.00|

6   $ printf "%s's average was %.1f%%./n" "Jody" $(( (80+70+90)/3 ))

    Jody's average was 80.0%.

说明  

1. 显示 printf 命令的 GNU 版本。

2. 如果使用的是 bash 2.x printf 是一个内置命令。

3. 按照说明符 %.2f 指定的格式,参数 100 以保留两位小数的浮点数形式输出。与 C 函数不同的是,这里不需要用逗号来分隔参数。

4. 格式串指明将进行 3 个变换:第一个是 %-20s( 一个左对齐,长度为 20 的字符串 ) ,接着是 %-15s( 一个左对齐,长度为 15 的字符串 ) ,最后一个则是 %10.2f( 一个右对齐,长度为 10 的浮点数,其中的一个字符是句点,最后两个字符是小数点右边的两个数 ) 。参数按对应 % 号的顺序被格式化,因此字符串 Jody 对应第一个 % ,字符串 Savage 对应第二个 % ,数字 28 则对应最后一个 % 号。

5. 该行和第 4 行一样,唯一的区别是增加了竖杠以说明串是左对齐还是右对齐的。

6. printf 命令格式化字符串 Jody 和算术扩展的结果 ( 请参见 13.13 节, 算术扩展 ”) 。需要两个百分号 (%%) 才能输出一个百分号 (%)

13.10.8   变量扩展修饰符

我们可以用一些专用修饰符来测试和修改变量。修饰符首先提供一个简单的条件测试,用来检查某个变量是否已经被设置,然后根据测试结果给变量赋一个值。请参见表13-18 列出的变量修饰符。

13-18  变量修饰符

   

${variable:-word}

如果变量 variable 已被设置且非空,则代入它的值。否则,代入 word

${variable:=word}

已被设置且值非空,就代入它的值。否则,将 variable 的值设为 word 。始终代入 variable 的值。位置参量不能用这种方式赋值

${variable:+word}

如果变量 variable 已被设置且值非空,代入 word 。否则,什么都不代入 ( 代入空值 )

${variable:?word}

如果变量 variable 已被设置且值非空,就代入它的值。否则,输出 word 并且从 shell 退出。如果省略了 word ,就会显示信息: parameter null or not set

${variable:offset}

获得变量 variable 值中位置从 offset 开始的子串,偏移为从 0 到串的末尾 19

${variable:offset:length}

获得变量 variable 值中位置从 offset 开始长度为 length 的子串

和冒号配合使用时,修饰符(-=+?) 检查变量是否尚未赋值或值为空。不加冒号时,值为空的变量也被认为已设置。

范例 13-60

( 临时替换默认值 )

1   $ fruit=peach

2   $ echo ${fruit:–plum}

    peach

3   $ echo ${newfruit:–apple}

    apple

4   $ echo $newfruit

5   $ echo $EDITOR       # More realistic example

6   $ echo ${EDITOR:-/bin/vi}

    /bin/vi

7   $ echo $EDITOR

8   $ name=

    $ echo ${name-Joe}

9   $ echo ${name:-Joe}

    Joe

说明

1. 将变量 fruit 的值设为 peach

2. 这个专用修饰符将检查变量 fruit 是否已被设置。如果 fruit 已被设置,就显示它。否则,用 plum 替换 fruit ,并显示该值。

3. 变量 newfruit 未曾被设置。值 apple 将暂时替换 newfruit

4. 上一行的设置是暂时的,因此,变量 newfruit 仍未被设置。

5. 环境变量 EDITOR 尚未被设置。

6. 修饰符 :- /bin/vi 替换为 EDITOR

7. EDITOR 未曾被设置过,因此什么都不会打印。

8. 变量 name 被设为空值。因为修饰符前面没有冒号,变量即使为空也被认为是设置过的,所以没有把新的值 Joe 赋给变量 name

9. 冒号使得修饰符检查变量是否未设置或为空。只要是这两种情况之一,就用值 Joe 替换 name

范例 13-61

( 永久替换默认值 )

1   $ name=

2   $ echo  ${name:=Peter}

    Peter

3   $ echo $name

    Peter

4   $ echo ${EDITOR:=/bin/vi}

    /bin/vi

5   $ echo $EDITOR

    /bin/vi

说明

1. 赋给变量 name 一个空值。

2. 用修饰符 := 将检查变量 name 是否尚未被设置。如果已经被设置过了,就不会被改变。如果尚未设置或值为空,就将等号右边的值赋给它。由于之前已将变量 name 设置为空,所以现在要把 Peter 赋给它。这个设置是持久的。

3. 变量 name 的值还是 Peter

4. 把变量 EDITOR 设置为 /bin/vi

5. 显示变量 EDITOR 的值。

范例 13-62

( 临时替换值 )

1   $ foo=grapes

2   $ echo ${foo:+pears}

    pears

3   $ echo $foo

    grapes

    $

说明

1. 将变量 foo 的值设置为 grapes

2. 专用修饰符 := 将检查变量 name 是否已被设置。如果已经被设置过,就用 pears 暂时替换 foo 。否则,返回空。

3. 变量 foo 的值还是原来的值。

范例 13-63

( 基于默认值创建错误信息 )

1   $ echo ${namex:?"namex is undefined"}

    namex: namex is undefined

2   $ echo ${y?}

    y: parameter null or not set

说明  

1. 修饰赋 :? 检查变量是否已被设置。如果尚未设置该变量,就把问号右边的信息打印在标准错误输出上。如果此时是在执行脚本,就退出脚本。

2. 如果问号后面没有提供报错信息, shell 就向标准错误输出发送默认的消息。

范例 13-64

( 创建子串 20 )

1   $ var=notebook

2   $ echo ${var:0:4}

    note

3   $ echo ${var:4:4}

    book

4   $ echo ${var:0:2}

    no

说明

1. 给变量赋值 notebook

2. var 的子串从偏移 0(notebook 中的 n) 开始,长度为 4 个字符,在 e 处结束。

3. var 的子串从偏移 4(notebook 中的 b) 开始,长度为 4 个字符,在 k 处结束。

4. var 的子串从偏移 0(notebook 中的 n) 开始,长度为 2 个字符,在 o 处结束。

13.10.9   子串的变量扩展

模式匹配变量用来在串首或串尾截掉串的某一特定部分。这些操作符最常见的用法是从路径头或尾删除路径名元素。如表13-19 所示。

13-19  变量扩展子串

   

   

${ 变量 % 模式 }

将变量值的尾部与模式进行最小匹配,并将匹配到的部分删除

${ 变量 %% 模式 }

将变量值的尾部与模式进行最大匹配,并将匹配到的部分删除

${ 变量 # 模式 }

将变量值的头部与模式进行最小匹配,并将匹配到的部分删除

${ 变量 ## 模式 }

将变量值的头部与模式进行最大匹配,并将匹配到的部分删除

${# 变量 }

替换为变量中的字符个数。如果是 * @ ,长度则是位置参量的个数

范例 13-65

1   $ pathname="/usr/bin/local/bin"

2   $ echo ${pathname%/bin*}

    /usr/bin/local

说明

1. 给局部变量 pathname 赋值 /usr/bin/local/bin

2. % 删除路径名尾部包含模式 /bin ,后跟零个或多个字符的最小部分。即删除 /bin

范例 13-66

1   $ pathname="usr/bin/local/bin"

2   $ echo ${pathname%%/bin*}

    /usr

说明

1. 给局部变量 pathname 赋值 /usr/bin/local/bin

2. %% 删除路径名尾部包含模式 /bin ,后跟零个或多个字符的最大部分。即删除 /bin/local/bin

范例13-67

1   $ pathname=/home/lilliput/jake/.bashrc

2   $ echo ${pathname#/home}

    /lilliput/jake/.bashrc

说明

1. 给局部变量 pathname 赋值 /home/liliput/jake/.bashrc

2. # 删除路径名头部包含模式/home 的最小部分。路径变量开头的/home 被删除。

范例 13-68

1   $ pathname=/home/lilliput/jake/.bashrc

2   $ echo ${pathname##*/}

    .bashrc

说明

1. 给局部变量 pathname 赋值 /home/liliput/jake/.bashrc

2. ## 删除路径名的头部包含零个或多个字符,直到并包括最后一个斜杠的最大部分。即从路径变量中删除 /home/liliput/jake/

范例13-69

1   $ name="Ebenezer Scrooge"

2   $ echo  ${#name}

    16

说明

1. 给变量 name 赋值 Ebenezer Scrooge

2. ${#variable} 语法显示赋给变量 name 的字符串中字符的个数。字符串 Ebenezer Scrooge 中有 16 个字符。

13.10.10   位置参量

这组专用内置变量常常被称为位置参量,通常被shell 脚本用来从命令行接收参数,或者被函数用来保存传给它的参数。这组变量之所以被称为位置参量,是因为引用它们要用到123 等数字,这些数字分别代表它们在参数列表中的相应位置。请参见表13-20

13-20  位置参量

   

   

$0

指代当前 shell 脚本的名称

$1-$9

代表第 1 个到第 9 个位置参量

${10}

10 个位置参量

$#

其值为位置参量的个数

$*

其值为所有的位置参量

$@

除了被双引号引用的情况,含义与 $* 相同

"$*"

其值为 "$1 $2 $3"

"$@"

其值为 "$1" "$2" "$3"

shell 脚本名存在变量$0 中。位置参量可以用set 命令来设置,重置和复位。

范例 13-70

1   $ set punky tommy bert jody

    $ echo $*            # Prints all the positional parameters

    punky tommy bert jody

2   $ echo $1           # Prints the first position

    punky

3   $ echo $2 $3       # Prints the second and third position

    tommy bert

4   $ echo $#           # Prints the total number of positional parameters

    4

5   $ set a b c d e f g h i j k l m

    $ print $10         # Prints the first positional parameter followed by a 0

    a0

    $ echo ${10} ${11} # Prints the 10th and 11th positions

    j k

6   $ echo $#

    13

7   $ echo $*

    a b c d e f g h i j k l m

8   $ set file1 file2 file3

    $ echo /$$#

    $3

9   $ eval echo /$$#

    file3

10  $ set --            # Unsets all positional parameters

  说明

1. set 命令给位置参量赋值。专用变量 $* 包含所有的位置参量。

2. 显示第 1 个位置参量的值, punky

3. 显示第 2 和第 3 个位置参量的值, tommy bert

4. 专用变量 $# 的值是当前已设置的位置参量的个数。

5. set 命令复位所有的位置参量。原来的位置参量集被清除。要打印 9 以上的任意位置参量,就要用花括号把两个数字括起来。否则,就打印第一个位置参量的值,后跟另一个数。

6. 位置参量个数现在是 13

7. 显示所有位置参量的值。

8. 美元符被转义, $# 是参数个数。 echo 命令显示 $3 ,一个美元符号后跟位置参量的个数。

9. 执行命令之前, eval 命令对命令行进行第二次解析。第一次由 shell 解析,将输出 $3 。第二次由 eval 解析,显示 $3 的值,即 file3

10. -- 选项的 set 命令清除或复位所有的位置参量。

13.10.11   其他特殊变量

shell 有一些由单个字符组成的特殊变量。在字符前面加上美元符就能访问变量中保存的值。如表13-21 所示。

13-21  特殊变量

   

   

$

当前 shell PID

-

当前的 sh 选项设置              

?

已执行的上一条命令的退出值

!

最后一个进入后台的作业的 PID

范例 13-71

1   $ echo The pid of this shell is $$

    The pid of this shell is 4725

2   $ echo The options for this shell are $–

    The options for this shell are imh

3   $ grep dodo /etc/passwd

    $ echo $?

    1

4   $ sleep 25&

    4736

    $ echo $!

    4736

说明

1. 变量 $ 保存这个进程的 PID 值。

2. 变量 列出当前这个交互式 bash shell 的所有选项。

3. grep 命令在 /etc/passwd 文件中查找字符串 dodo 。变量?保存了上一条被执行的命令的退出状态。由于 grep 返回的值是 1 ,因此可以假定 grep 的查找失败了。退出状态 0 代表成功退出。

4. 变量!保存上一条被放入后台的命令的 PID 号。 sleep 命令后面的 & 把命令发到后台。

 

你可能感兴趣的:(shell)