Linux Shell编程学习笔记(3)

时间:2021-01-30 00:15:37

Linux Shell编程学习笔记(2015-7-19)

分类:linux shell

一:位置参数和特殊变量

  什么是位置参数?
  位置参数也叫位置变量,是运行shell脚本程序时,命令行shell传递给脚本的参数,以及在shell脚本程序中调用函数时传递给函数的参数。这些位置变量的名称很特别,是以0,1,2,3….这些整数命名的。
  位置变量的数字与参数出现的具体位置相对应:0对应命令名,1对应第一个实参,2对应第二个实参…以此类推。响应地,使用 0, 1, 2...使 {10}, ${11}。
  几个特殊含义的shell变量

特殊变量 含义
$# 命令行上参数的个数,但不包含shell脚本名本身
| 0
@|1 0。如果放在双引号中进行扩展,则“ @ 1”,“ 2 3”…等效。
$? 上一条命令执行后的返回值
$$ 运行脚本的当前进程的进程号
$! 上一个后台命令对应的进程号
$- 由当前shell设置的执行标志名组成的字符串

比如下面的一个shell程序posvar.sh

#! /bin/bash
echo 'Parameter number:' $#
echo 'All digit variables:' $0 $1 $2 $3 $4 $5 $6 $7 $8 $9 ${10} ${11}
echo '$*:' $*
echo 下面输出'$@'的所有内容
echo $@

它的运行结果如下:

biantiao@lazybone1994-ThinkPad-E430:~/sh$ ./posvar.sh 1 2 3 4 5 6 7 8 9 10 11
Parameter number: 11
All digit variables: ./posvar.sh 1 2 3 4 5 6 7 8 9 10 11
$*: 1 2 3 4 5 6 7 8 9 10 11
下面输出$@的所有内容
1 2 3 4 5 6 7 8 9 10 11
biantiao@lazybone1994-ThinkPad-E430:~/sh$

  使用set命令间接地设置除$0以外的位置变量的值。
比如下面的例子setvar.sh

#! /bin/bash
set learning linux shell
echo $0 $1 $2 $3

它的运行结果为:

biantiao@lazybone1994-ThinkPad-E430:~/sh$ ./setvar.sh
./setvar.sh learning linux shell
biantiao@lazybone1994-ThinkPad-E430:~/sh$

  shell还内置了一个shift命令,用来向左移动位置参数,即:原来的 3 2,原来的 2 1,$1的值永远丢失。以此类推。结果是参数的个数少了一个。
比如下面的shiftposvar.sh:

#! /bin/bash
set learning linux shell
echo "Parameter number: $#, there are:"
echo $1 $2 $3
shift
echo 位置参数向左移动一位后,参数的情况为:
echo "Parameter number: $#, there are:"
echo $1 $2 $3

它的运行结果为:

biantiao@lazybone1994-ThinkPad-E430:~/sh$ ./shiftposvar.sh
Parameter number: 3, there are:
learning linux shell
位置参数向左移动一位后,参数的情况为:
Parameter number: 2, there are:
linux shell
biantiao@lazybone1994-ThinkPad-E430:~/sh$

二:read命令

  Linux Shell提供了read命令用于从键盘上读取数据并赋值给指定变量。利用read命令可以编写交互式的脚本程序。read命令的一般格式是:
read 变量1 [变量2...]
  注意:输入数据时,数据项之间应该以空格或者制表符作为分隔符。
  变量个数与数据个数之间可能出现以下三种情况:
- 变量个数与给定数据个数之间相同,则依次赋值。例如:

biantiao@lazybone1994-ThinkPad-E430:~$ read a b c
linux shell programming
biantiao@lazybone1994-ThinkPad-E430:~$ echo $a $b $c
linux shell programming
biantiao@lazybone1994-ThinkPad-E430:~$
  • 变量个数少于数据个数,则从左至右对应赋值,但最后一个变量被赋予剩下的所有数据。例如:
biantiao@lazybone1994-ThinkPad-E430:~$ read a b c
learning linux shell programming
biantiao@lazybone1994-ThinkPad-E430:~$ echo $a $b $c
learning linux shell programming
biantiao@lazybone1994-ThinkPad-E430:~$ echo $c
shell programming
biantiao@lazybone1994-ThinkPad-E430:~$
  • 变量个数多于给定的数据个数,则依次对应赋值,而没有数据与之对应的变量取空串。例如:
biantiao@lazybone1994-ThinkPad-E430:~$ read a b c
linux shell
biantiao@lazybone1994-ThinkPad-E430:~$ echo $a $b
linux shell
biantiao@lazybone1994-ThinkPad-E430:~$ echo $c

biantiao@lazybone1994-ThinkPad-E430:~$

三:export语句

  首先先来说说Linux中的变量的可见性。
  在linux中用户可以在脚本或着命令行上定义一些变量并赋值,包括改变环境变量。在同一shell中,变量值是可见的;但在子shell中,父shell的变量是不可见的。例如下面的例子,在child.sh的脚本当中将要显示str的值。bash运行该脚本时将创建一个子进程。但脚本中要求显示的str是shell当中的变量,它并不在子进程中。我们来看看会有什么结果。

biantiao@lazybone1994-ThinkPad-E430:~$ cd sh
biantiao@lazybone1994-ThinkPad-E430:~/sh$ cat child.sh
#! /bin/bash
echo $str

biantiao@lazybone1994-ThinkPad-E430:~/sh$ str="parent shell variable"
biantiao@lazybone1994-ThinkPad-E430:~/sh$ bash child.sh

biantiao@lazybone1994-ThinkPad-E430:~/sh$ ./child.sh

biantiao@lazybone1994-ThinkPad-E430:~/sh$ source child.sh
parent shell variable
biantiao@lazybone1994-ThinkPad-E430:~/sh$

说明:上面出现了source命令,使用source命令来运行了child.sh脚本。我们来复习一下source命令:source命令是shell的内部命令,使用它来执行脚本系统不会创建新的进程,也即:使用source命令执行的脚本在当前的进程中被执行。所以以上的实例中使用source命令执行的脚本仍然可以将str显示出来。
  总结来说就是:在命令行上输入的命令都是由相应的进程执行的,即父进程创建子进程,子进程完成该命令的功能。然而,子进程执行时的环境与父进程的环境往往不同。一个进程在自己的环境中定义的是局部变量,仅限于自身的范围,不能传递给其子进程。父进程定义的变量对其子进程的运行环境不产生任何影响。
  那么问题来了,怎样才能使各个子进程能够继承父进程中定义的变量呢?答案是:使用export命令。在父进程中使用export命令将要在子进程中使用的变量转出到进程转出区(子进程可以继承父进程中的转出区中的数据)。
  export命令的一般格式是export 变量名。举个例子:

biantiao@lazybone1994-ThinkPad-E430:~$ cd sh
biantiao@lazybone1994-ThinkPad-E430:~/sh$ cat child.sh
#! /bin/bash
echo $str

biantiao@lazybone1994-ThinkPad-E430:~/sh$ str="来自父进程中的变量str"
biantiao@lazybone1994-ThinkPad-E430:~/sh$ export str
biantiao@lazybone1994-ThinkPad-E430:~/sh$ bash child.sh
来自父进程中的变量str
biantiao@lazybone1994-ThinkPad-E430:~/sh$

说明:在同一个export命令行上可以有多个变量名。子shell中可以读取但无法改变父shell中export出来的变量。