linux Shell学习笔记1
1.简介
Shell 同时是一个命令解释器和一门编程语言
作为命令解释器(command interpreter),
shell 为用户提供 UNIX/Linux 系统内核(kernel)的接口,使其能使用其多种工具集,
而其编程语言功能
使得这些工具能够连接起来。
2.学习方法
学习 shell 的过程中除了要掌握其如何定义变量、使用条件、循环等功能外,还应特别注意掌握如何通过各种方式配置其环境
3.特征
Bash 相对 sh 的特征主要有:
` 目录处理,包含 pushd, popd 和 dirs 命令
` 作业控制,包括 fg 和 bg 命令,以及使用 CRTL-Z 停止作业
` 大括号扩展,可以产生任意的字符串扩展,指代用户根目录的缩写
` ~扩展,指代用户根目录的缩写
` 别名,让你为命令或命令行定义缩写名称
` 命令历史,让你记得以前输入的指令
以上源于 C shell。
` 命令行编辑,使用 emacs 或 vi 风格
` 键盘绑定,让你设置自定义编辑的键序列
` 集成编程特性,包含几个 UNIX 外部命令的功能,包括 test、expr、getopt、echo
等,使得编程任务能更简洁有效地完成
` 控制结构,特别是 select 结构,能简单生成菜单
` 新的选项与变量,使得你有更多的途径来定制你的环境
` 一维数组,使得引用与操作数据列表更为简单
` 动态加载 built-in 命令,自定义命令并加载进 shell 的功能。
===================================
1.启动
1.1 Bash启动选项
1.2 交互式启动
交互式包括两种方式:作为 login shell 或者 non-login shell。
交互式 login 启动时读取以下系统级别和用户级别的启动文件;交互式 non-login 启动时读
取以下 Bash 级别启动文件。
因此,Bash 提供了三种级别的环境配置,分别与三种初始化文件对应:
(1) 系统级别,由/etc/profile 文件控制。这个文件在 Bash shell 启动时被执行。它可被
系统所有 sh 和 ksh 用户使用。
(2) 用户级别,由~/.bash_profile(或者~/.bash_login,或者~/.profile)和~/.bash_logout
文件控制。这些文件控制登录用户的基本登录和退出环境。
,由~/.bashrc 文件控制。每次一个新的 Bash shell 启动时
(3) Bash 级别(子 shell 级别)
将自动执行~/.bashrc 文件,用来配置只属于 Bash shell 的环境。~/.bashrc 一般会含
有以下语句:
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
/etc/bashrc 一般用来设置所有 Bash shell 公用的变量
系统配置文件/etc/profile 文件
用户级别的三个登录配置文件(~/.bash_profile,~/.bash_login 和~/.profile)中
1.3非交互式启动
2 注释与帮助
#!/bin/bash
如果是针对 Bash 编程,一定要在首行加上#!/bin/bash,以防止脚本被错误的 shell 执行。
man info help 3个
================================================
3 变量与数组
一.变量分类
Bash 的变量按作用域可分为两类:
局部变量和环境变量(全局变量)
局部变量只在创建它们的 shell 中可用。(loacl )
环境变量在创建他们的shell 及其派生子进程中使用。
Bash 的变量又可以按照是否是用户创建的分为:
用户定义变量和专有shell 变量。
说明:
1.局部变量可以通过简单赋值或一个变量名来设置,或者用 declare 内置函数来设置(不含-x 选项)。
内置函数 local 可以用来创建局部变量,但仅限于在函数内使用。
函数不使用 local 的变量在整个 shell 中是可见的。
2.环境变量可以用 declare –x 命令或者 export varname=value 命令来设置。
二.变量的命名与赋值
1.命名规则:变量名大小敏感.变量名必须以字母或下划线字符开头,其余的字符可以是字母、数字
或下划线字符。任何其他字符标志着变量名的终止
2.变量赋值:给变量赋值时,等号周围不能有任何空白符!!!为了给变量赋空值,可以在等
号后跟一个换行符。格式: name=[value]
注:
1.初学者很容易犯在等号左右加空格的错误,必须注意!
这是 shell 极特别的地方,因为几乎所有的编程语言都允许甚至建议=左右加空格
2.变量定义时前面不加$符号,而在引用时需要加。Bash 的这一特点与 AWK 和 Perl
都有差别: AWK 无论定义和引用都不加$符号,而 Perl 的标量无论定义和引用都需
要加$符
3.$name 是更一般形式的${name}的简单形式。两者在大多数时候是可以互换的,但
是在可能引起歧义时需要加{}表示对某一变量的引用。如果变量名跟随一个不是字
母、数字或下划线的字符,则可以省略括号。
4.给变量赋值的另一方式是变量替换。Bash 的标准方式是$(UNIX command),同时
bash 也兼容 Bourne shell 的`Unix command`方式。但是建议使用 Bash 的标准方式,
因为这种方式更灵活,而且不容易出错(``方式很容易与单引号混淆)
3.declare 选项
选项 含 义
-a 将变量当作一个数组。即分配元素
-f 列出函数的名称和定义
-F 只列出函数名
-i 将变量设为整型
-r 将变量设为只读
-x 将变量输出到子 shell 中,相当于定义后用 export 将其变为环境变量
4 位置和特殊参量
首先说说参量与变量的区别:参量(parameter)是储存值的实体,它可以是一个名字、一个数或者特殊的字符(放在执行命令的程序名字后面的参数);
变量(variable)是以名字命名的参量。
变量有一个值和 0 或多个属性,属性通过以上 declare 选项来设置。
位置和特殊参量 指 代 对 象
$0 脚本名
$# 位置参数个数
$* 所有的位置参数
$@ 未加引号时与$*的含义相同
$1...${N} 单独的位置变量
$$ 当前 shell 的 PID
$! 最后一个进入后台的作业 PID
$- 当前的 sh 选项设置
$? 已执行的上一条命令的退出值
$_ 上一条命令的最后一个参数
注:
$*是一个由所有位置参量组成的单一的字符串,由环境变量 IFS 第一个字符分隔;相当于”$1c$2c...”, c 是 IFS 的第一个字符;
$@是 N 个独立的双引字符串,由空格分隔,即相当于”$1” “$2” ... “$N”。//故最好使用 $@ 统计参数个数
5 环境变量
环境变量是已经用 export 内置命令导出的变量,可在创建它们的 shell 及其子 shell 中使用。
环境变量可能在/bin/login 程序,.bash_profile 文件中定义。
6 数组
Bash 支持一维数组,指标默认从 0 开始。
数组赋值的方式有:
names=([2]=alice [0]=hatter [1]=duchess)
names=(hatter duchess alice)
names=(hatter [5]=duchess alice) #names[0]=hatter names[5]=duchess names[6]=alice
数组元素的引用方式: ${array[i]}
所有元素使用(@和*):
for i in “${names[@]}” ; do
echo $i
done
使用 ${!array[@]} 来获取有值的数组指标。使用 ${#array[i]}来获取某一数组元素的长度,
${#array[@]}或${#array[*]}是数组长度(非 null 元素个数)
如果对数组重新赋值,原数组元素将会消失。可以使用 unset 命令删除整个数组或数组的某
一个元素: unset array 或者 unset array[i]
说明:Bash 的数组与 C 的区别:C 中如果定义了 array[1000],则 array[0]~array[999]都一
定是存在的,而 Bash 则不然
7.关于输入、输出和错误输出
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序 或命令的输入,
无论是从键盘输入还是从别的文件输入;输出即指应用程序或命令产生的一些信息;与 Windows 系统下不同的是,
Linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,
错误输出于标准输出分开可以让一些高级的错误信息不干扰正常的输出 信息,从而方便一般用户的使用。
在 Linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;
标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为
1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。
输入、输出及标准错误输出主要用于 I/O 的重定向,就是说需要改变他们的默认设置。先看这个例子:
$ ls > ls_result
$ ls -l >> ls_result
上面这两个命令分别将 ls 命令的结果输出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是输出到屏幕上。
">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出。下面再来看一个稍微复杂的例子:
$ find /home -name lost* 2> err_result
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,
因此会产生一些标准错误输出被存放在 err_result 文件中。大家可以设想一下 find /home -name lost* 2>>err_result 命令会产生什么结果?
如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中,
要想让标准错误输出和标准输入一样都被存入到文件中,那该怎么办呢?看下面这个例子:
$ find /home -name lost* > all_result 2>& 1
上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。
这样我们就可以将所有的输出都存储到文件中了。为实现上述功能,还有一种简便的写法如下:
$ find /home -name lost* >& all_result
如果那些出错信息并不重要,下面这个命令可以让你避开众多无用出错信息的干扰:
$ find /home -name lost* 2> /dev/null
同学们回去后还可以再试验一下如下几种重定向方式,看看会出什么结果,为什么?
$ find /home -name lost* > all_result 1>& 2
$ find /home -name lost* 2> all_result 1>& 2
$ find /home -name lost* 2>& 1 > all_result
另外一个非常有用的重定向操作符是 "-",请看下面这个例子:
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去,
这个命令在 /source/directory 和 /dest/directory 不处在同一个文件系统下时将显示出特别的优势。
下面还几种不常见的用法:
n<&- 表示将 n 号输入关闭
<&- 表示关闭标准输入(键盘)
n>&- 表示将 n 号输出关闭
>&- 表示将标准输出关闭
8 变量
BASH 中的变量既然不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,
也可以被再定义为整数。如果对该变量进行整数运算,
他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串
关于整数变量计算,有如下几种:" + - * / % ",他们的意思和字面意思相同。整数运算一般通过 let 和 expr 这两个指令来实现,
如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`
在比较操作上,整数变量和字符串变量各不相同,详见下表:对应的操作
整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt <
大于或等于 -ge
小于或等于 -le
为空 -z
不为空 -n
Shell 同时是一个命令解释器和一门编程语言
作为命令解释器(command interpreter),
shell 为用户提供 UNIX/Linux 系统内核(kernel)的接口,使其能使用其多种工具集,
而其编程语言功能
使得这些工具能够连接起来。
2.学习方法
学习 shell 的过程中除了要掌握其如何定义变量、使用条件、循环等功能外,还应特别注意掌握如何通过各种方式配置其环境
3.特征
Bash 相对 sh 的特征主要有:
` 目录处理,包含 pushd, popd 和 dirs 命令
` 作业控制,包括 fg 和 bg 命令,以及使用 CRTL-Z 停止作业
` 大括号扩展,可以产生任意的字符串扩展,指代用户根目录的缩写
` ~扩展,指代用户根目录的缩写
` 别名,让你为命令或命令行定义缩写名称
` 命令历史,让你记得以前输入的指令
以上源于 C shell。
` 命令行编辑,使用 emacs 或 vi 风格
` 键盘绑定,让你设置自定义编辑的键序列
` 集成编程特性,包含几个 UNIX 外部命令的功能,包括 test、expr、getopt、echo
等,使得编程任务能更简洁有效地完成
` 控制结构,特别是 select 结构,能简单生成菜单
` 新的选项与变量,使得你有更多的途径来定制你的环境
` 一维数组,使得引用与操作数据列表更为简单
` 动态加载 built-in 命令,自定义命令并加载进 shell 的功能。
===================================
1.启动
1.1 Bash启动选项
1.2 交互式启动
交互式包括两种方式:作为 login shell 或者 non-login shell。
交互式 login 启动时读取以下系统级别和用户级别的启动文件;交互式 non-login 启动时读
取以下 Bash 级别启动文件。
因此,Bash 提供了三种级别的环境配置,分别与三种初始化文件对应:
(1) 系统级别,由/etc/profile 文件控制。这个文件在 Bash shell 启动时被执行。它可被
系统所有 sh 和 ksh 用户使用。
(2) 用户级别,由~/.bash_profile(或者~/.bash_login,或者~/.profile)和~/.bash_logout
文件控制。这些文件控制登录用户的基本登录和退出环境。
,由~/.bashrc 文件控制。每次一个新的 Bash shell 启动时
(3) Bash 级别(子 shell 级别)
将自动执行~/.bashrc 文件,用来配置只属于 Bash shell 的环境。~/.bashrc 一般会含
有以下语句:
if [ -f /etc/bashrc ]; then
. /etc/bashrc
fi
/etc/bashrc 一般用来设置所有 Bash shell 公用的变量
系统配置文件/etc/profile 文件
用户级别的三个登录配置文件(~/.bash_profile,~/.bash_login 和~/.profile)中
1.3非交互式启动
2 注释与帮助
#!/bin/bash
如果是针对 Bash 编程,一定要在首行加上#!/bin/bash,以防止脚本被错误的 shell 执行。
man info help 3个
================================================
3 变量与数组
一.变量分类
Bash 的变量按作用域可分为两类:
局部变量和环境变量(全局变量)
局部变量只在创建它们的 shell 中可用。(loacl )
环境变量在创建他们的shell 及其派生子进程中使用。
Bash 的变量又可以按照是否是用户创建的分为:
用户定义变量和专有shell 变量。
说明:
1.局部变量可以通过简单赋值或一个变量名来设置,或者用 declare 内置函数来设置(不含-x 选项)。
内置函数 local 可以用来创建局部变量,但仅限于在函数内使用。
函数不使用 local 的变量在整个 shell 中是可见的。
2.环境变量可以用 declare –x 命令或者 export varname=value 命令来设置。
二.变量的命名与赋值
1.命名规则:变量名大小敏感.变量名必须以字母或下划线字符开头,其余的字符可以是字母、数字
或下划线字符。任何其他字符标志着变量名的终止
2.变量赋值:给变量赋值时,等号周围不能有任何空白符!!!为了给变量赋空值,可以在等
号后跟一个换行符。格式: name=[value]
注:
1.初学者很容易犯在等号左右加空格的错误,必须注意!
这是 shell 极特别的地方,因为几乎所有的编程语言都允许甚至建议=左右加空格
2.变量定义时前面不加$符号,而在引用时需要加。Bash 的这一特点与 AWK 和 Perl
都有差别: AWK 无论定义和引用都不加$符号,而 Perl 的标量无论定义和引用都需
要加$符
3.$name 是更一般形式的${name}的简单形式。两者在大多数时候是可以互换的,但
是在可能引起歧义时需要加{}表示对某一变量的引用。如果变量名跟随一个不是字
母、数字或下划线的字符,则可以省略括号。
4.给变量赋值的另一方式是变量替换。Bash 的标准方式是$(UNIX command),同时
bash 也兼容 Bourne shell 的`Unix command`方式。但是建议使用 Bash 的标准方式,
因为这种方式更灵活,而且不容易出错(``方式很容易与单引号混淆)
3.declare 选项
选项 含 义
-a 将变量当作一个数组。即分配元素
-f 列出函数的名称和定义
-F 只列出函数名
-i 将变量设为整型
-r 将变量设为只读
-x 将变量输出到子 shell 中,相当于定义后用 export 将其变为环境变量
4 位置和特殊参量
首先说说参量与变量的区别:参量(parameter)是储存值的实体,它可以是一个名字、一个数或者特殊的字符(放在执行命令的程序名字后面的参数);
变量(variable)是以名字命名的参量。
变量有一个值和 0 或多个属性,属性通过以上 declare 选项来设置。
位置和特殊参量 指 代 对 象
$0 脚本名
$# 位置参数个数
$* 所有的位置参数
$@ 未加引号时与$*的含义相同
$1...${N} 单独的位置变量
$$ 当前 shell 的 PID
$! 最后一个进入后台的作业 PID
$- 当前的 sh 选项设置
$? 已执行的上一条命令的退出值
$_ 上一条命令的最后一个参数
注:
$*是一个由所有位置参量组成的单一的字符串,由环境变量 IFS 第一个字符分隔;相当于”$1c$2c...”, c 是 IFS 的第一个字符;
$@是 N 个独立的双引字符串,由空格分隔,即相当于”$1” “$2” ... “$N”。//故最好使用 $@ 统计参数个数
5 环境变量
环境变量是已经用 export 内置命令导出的变量,可在创建它们的 shell 及其子 shell 中使用。
环境变量可能在/bin/login 程序,.bash_profile 文件中定义。
6 数组
Bash 支持一维数组,指标默认从 0 开始。
数组赋值的方式有:
names=([2]=alice [0]=hatter [1]=duchess)
names=(hatter duchess alice)
names=(hatter [5]=duchess alice) #names[0]=hatter names[5]=duchess names[6]=alice
数组元素的引用方式: ${array[i]}
所有元素使用(@和*):
for i in “${names[@]}” ; do
echo $i
done
使用 ${!array[@]} 来获取有值的数组指标。使用 ${#array[i]}来获取某一数组元素的长度,
${#array[@]}或${#array[*]}是数组长度(非 null 元素个数)
如果对数组重新赋值,原数组元素将会消失。可以使用 unset 命令删除整个数组或数组的某
一个元素: unset array 或者 unset array[i]
说明:Bash 的数组与 C 的区别:C 中如果定义了 array[1000],则 array[0]~array[999]都一
定是存在的,而 Bash 则不然
7.关于输入、输出和错误输出
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序 或命令的输入,
无论是从键盘输入还是从别的文件输入;输出即指应用程序或命令产生的一些信息;与 Windows 系统下不同的是,
Linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,
错误输出于标准输出分开可以让一些高级的错误信息不干扰正常的输出 信息,从而方便一般用户的使用。
在 Linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;
标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为
1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。
输入、输出及标准错误输出主要用于 I/O 的重定向,就是说需要改变他们的默认设置。先看这个例子:
$ ls > ls_result
$ ls -l >> ls_result
上面这两个命令分别将 ls 命令的结果输出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是输出到屏幕上。
">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出。下面再来看一个稍微复杂的例子:
$ find /home -name lost* 2> err_result
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,
因此会产生一些标准错误输出被存放在 err_result 文件中。大家可以设想一下 find /home -name lost* 2>>err_result 命令会产生什么结果?
如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中,
要想让标准错误输出和标准输入一样都被存入到文件中,那该怎么办呢?看下面这个例子:
$ find /home -name lost* > all_result 2>& 1
上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。
这样我们就可以将所有的输出都存储到文件中了。为实现上述功能,还有一种简便的写法如下:
$ find /home -name lost* >& all_result
如果那些出错信息并不重要,下面这个命令可以让你避开众多无用出错信息的干扰:
$ find /home -name lost* 2> /dev/null
同学们回去后还可以再试验一下如下几种重定向方式,看看会出什么结果,为什么?
$ find /home -name lost* > all_result 1>& 2
$ find /home -name lost* 2> all_result 1>& 2
$ find /home -name lost* 2>& 1 > all_result
另外一个非常有用的重定向操作符是 "-",请看下面这个例子:
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去,
这个命令在 /source/directory 和 /dest/directory 不处在同一个文件系统下时将显示出特别的优势。
下面还几种不常见的用法:
n<&- 表示将 n 号输入关闭
<&- 表示关闭标准输入(键盘)
n>&- 表示将 n 号输出关闭
>&- 表示将标准输出关闭
8 变量
BASH 中的变量既然不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,
也可以被再定义为整数。如果对该变量进行整数运算,
他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串
关于整数变量计算,有如下几种:" + - * / % ",他们的意思和字面意思相同。整数运算一般通过 let 和 expr 这两个指令来实现,
如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`
在比较操作上,整数变量和字符串变量各不相同,详见下表:对应的操作
整数操作 字符串操作
相同 -eq =
不同 -ne !=
大于 -gt >
小于 -lt <
大于或等于 -ge
小于或等于 -le
为空 -z
不为空 -n