📄 469.html
字号:
<br>
我们先来从整体上把握一下 BASH 中变量的用法,然后再去分析 BASH 中变量使用与 C 语言中的不同。BASH 中的变量都是不能含有保留字,不能含有 "-" 等保留字符,也不能含有空格。<br>
简单变量<br>
在 BASH 中变量定义是不需要的,没有 "int i" 这样的定义过程。如果想用一个变量,只要他没有在前面被定义过,就直接可以用,当然你使用该变量的第一条语句应该是对他赋初值了,如果你不赋初值也没关系,只不过该变量是空( 注意:是 NULL,不是 0 )。不给变量赋初值虽然语法上不反对,但不是一个好的编程习惯。好了我们看看下面的例子:<br>
<br>
首先用 vi 编辑下面这个文件 hello2:<br>
<br>
#!/bin/bash<br>
# give the initialize value to STR<br>
STR="Hello World"<br>
echo $STR<br>
<br>
在上面这个程序中我们需要注意下面几点:<br>
<br>
一,变量赋值时,'='左右两边都不能有空格;<br>
二,BASH 中的语句结尾不需要分号(";");<br>
三,除了在变量赋值和在FOR循环语句头中,BASH 中的变量使用必须在变量前加"$"符号,同学们可以将上面程序中第三行改为 "echo STR" 再试试,看看会出什么结果。<br>
四,由于 BASH 程序是在一个新的进程中运行的,所以该程序中的变量定义和赋值不会改变其他进程或原始 Shell 中同名变量的值,也不会影响他们的运行。<br>
<br>
更细致的文档甚至提到以但引号括起来的变量将不被 BASH 解释为变量,如 '$STR' ,而被看成为纯粹的字符串。而且更为标准的变量引用方式是 ${STR} 这样的,$STR 自不过是对 ${STR} 的一种简化。在复杂情况下(即有可能产生歧义的地方)最好用带 {} 的表示方式。<br>
<br>
BASH 中的变量既然不需要定义,也就没有类型一说,一个变量即可以被定义为一个字符串,也可以被再定义为整数。如果对该变量进行整数运算,他就被解释为整数;如果对他进行字符串操作,他就被看作为一个字符串。请看下面的例子:<br>
<br>
#!/bin/bash<br>
x=1999<br>
let "x = $x + 1"<br>
echo $x<br>
x="olympic'"$x<br>
echo $x<br>
<br>
关于整数变量计算,有如下几种:" + - * / % ",他们的意思和字面意思相同。整数运算一般通过 let 和 expr 这两个指令来实现,如对变量 x 加 1 可以写作:let "x = $x + 1" 或者 x=`expr $x + 1`<br>
<br>
在比较操作上,整数变量和字符串变量各不相同,详见下表:<br>
<br>
对应的操作 整数操作 字符串操作<br>
相同 -eq =<br>
不同 -ne !=<br>
大于 -gt ><br>
小于 -lt <<br>
大于或等于 -ge<br>
小于或等于 -le<br>
为空 -z<br>
不为空 -n<br>
<br>
<br>
比如:<br>
<br>
比较字符串 a 和 b 是否相等就写作:if [ $a = $b ]<br>
判断字符串 a 是否为空就写作: if [ -z $a ]<br>
判断整数变量 a 是否大于 b 就写作:if [ $a -gt $b ]<br>
<br>
更细致的文档推荐在字符串比较时尽量不要使用 -n ,而用 ! -z 来代替。(其中符号 "!" 表示求反操作)<br>
<br>
BASH 中的变量除了用于对 整数 和 字符串 进行操作以外,另一个作用是作为文件变量。BASH 是 linux 操作系统的 Shell,因此系统的文件必然是 BASH 需要操作的重要对象,如 if [ -x /root ] 可以用于判断 /root 目录是否可以被当前用户进入。下表列出了 BASH 中用于判断文件属性的操作符:<br>
<br>
运算符 含义( 满足下面要求时返回 TRUE )<br>
<br>
-e file 文件 file 已经存在<br>
-f file 文件 file 是普通文件<br>
-s file 文件 file 大小不为零<br>
-d file 文件 file 是一个目录<br>
-r file 文件 file 对当前用户可以读取<br>
-w file 文件 file 对当前用户可以写入<br>
-x file 文件 file 对当前用户可以执行<br>
-g file 文件 file 的 GID 标志被设置<br>
-u file 文件 file 的 UID 标志被设置<br>
-O file 文件 file 是属于当前用户的<br>
-G file 文件 file 的组 ID 和当前用户相同<br>
file1 -nt file2 文件 file1 比 file2 更新<br>
file1 -ot file2 文件 file1 比 file2 更老<br>
<br>
<br>
注意:上表中的 file 及 file1、file2 都是指某个文件或目录的路径。<br>
<br>
关于局部变量<br>
在 BASH 程序中如果一个变量被使用了,那么直到该程序的结尾,该变量都一直有效。为了使得某个变量存在于一个局部程序块中,就引入了局部变量的概念。BASH 中,在变量首次被赋初值时加上 local 关键字就可以声明一个局部变量,如下面这个例子:<br>
<br>
#!/bin/bash<br>
HELLO=Hello<br>
function hello {<br>
local HELLO=World<br>
echo $HELLO<br>
}<br>
echo $HELLO<br>
hello<br>
echo $HELLO<br>
<br>
该程序的执行结果是:<br>
<br>
Hello<br>
World<br>
Hello<br>
<br>
这个执行结果表明全局变量 $HELLO 的值在执行函数 hello 时并没有被改变。也就是说局部变量 $HELLO 的影响只存在于函数那个程序块中。<br>
<br>
BASH 中的变量与 C 语言中变量的区别<br>
这里我们为原来不熟悉 BASH 编程,但是非常熟悉 C 语言的程序员总结一下在 BASH 环境中使用变量需要注意的问题。<br>
<br>
1,BASH 中的变量在引用时都需要在变量前加上 "$" 符号( 第一次赋值及在For循环的头部不用加 "$"符号 );<br>
2,BASH 中没有浮点运算,因此也就没有浮点类型的变量可用;<br>
3,BASH 中的整形变量的比较符号与 C 语言中完全不同,而且整形变量的算术运算也需要经过 let 或 expr 语句来处理;<br>
<br>
<br>
<br>
[目录]<br>
<br>
--------------------------------------------------------------------------------<br>
<br>
<br>
输入输出<br>
<br>
关于输入、输出和错误输出<br>
在字符终端环境中,标准输入/标准输出的概念很好理解。输入即指对一个应用程序或命令的输入,无论是从键盘输入还是从别的文件输入;输出即指应用程序或命令产生的一些信息;与 Windows 系统下不同的是,linux 系统下还有一个标准错误输出的概念,这个概念主要是为程序调试和系统维护目的而设置的,错误输出于标准输出分开可以让一些高级的错误信息不干扰正常的输出信息,从而方便一般用户的使用。<br>
在 linux 系统中:标准输入(stdin)默认为键盘输入;标准输出(stdout)默认为屏幕输出;标准错误输出(stderr)默认也是输出到屏幕(上面的 std 表示 standard)。在 BASH 中使用这些概念时一般将标准输出表示为 1,将标准错误输出表示为 2。下面我们举例来说明如何使用他们,特别是标准输出和标准错误输出。<br>
<br>
输入、输出及标准错误输出主要用于 I/O 的重定向,就是说需要改变他们的默认设置。先看这个例子:<br>
<br>
$ ls > ls_result<br>
$ ls -l >> ls_result<br>
<br>
上面这两个命令分别将 ls 命令的结果输出重定向到 ls_result 文件中和追加到 ls_result 文件中,而不是输出到屏幕上。">"就是输出(标准输出和标准错误输出)重定向的代表符号,连续两个 ">" 符号,即 ">>" 则表示不清除原来的而追加输出。下面再来看一个稍微复杂的例子:<br>
<br>
$ find /home -name lost* 2> err_result<br>
<br>
这个命令在 ">" 符号之前多了一个 "2","2>" 表示将标准错误输出重定向。由于 /home 目录下有些目录由于权限限制不能访问,因此会产生一些标准错误输出被存放在 err_result 文件中。大家可以设想一下 find /home -name lost* 2>>err_result 命令会产生什么结果?<br>
<br>
如果直接执行 find /home -name lost* > all_result ,其结果是只有标准输出被存入 all_result 文件中,要想让标准错误输出和标准输入一样都被存入到文件中,那该怎么办呢?看下面这个例子:<br>
<br>
$ find /home -name lost* > all_result 2>& 1<br>
<br>
上面这个例子中将首先将标准错误输出也重定向到标准输出中,再将标准输出重定向到 all_result 这个文件中。这样我们就可以将所有的输出都存储到文件中了。为实现上述功能,还有一种简便的写法如下:<br>
<br>
$ find /home -name lost* >& all_result<br>
<br>
如果那些出错信息并不重要,下面这个命令可以让你避开众多无用出错信息的干扰:<br>
<br>
$ find /home -name lost* 2> /dev/null<br>
<br>
同学们回去后还可以再试验一下如下几种重定向方式,看看会出什么结果,为什么?<br>
<br>
$ find /home -name lost* > all_result 1>& 2<br>
$ find /home -name lost* 2> all_result 1>& 2<br>
$ find /home -name lost* 2>& 1 > all_result<br>
<br>
另外一个非常有用的重定向操作符是 "-",请看下面这个例子:<br>
<br>
$ (cd /source/directory && tar cf - . ) | (cd /dest/directory && tar xvfp -)<br>
<br>
该命令表示把 /source/directory 目录下的所有文件通过压缩和解压,快速的全部移动到 /dest/directory 目录下去,这个命令在 /source/directory 和 /dest/directory 不处在同一个文件系统下时将显示出特别的优势。<br>
<br>
下面还几种不常见的用法:<br>
<br>
n<&- 表示将 n 号输入关闭<br>
<&- 表示关闭标准输入(键盘)<br>
n>&- 表示将 n 号输出关闭<br>
>&- 表示将标准输出关闭<br>
<br>
<br>
<br>
[目录]<br>
<br>
--------------------------------------------------------------------------------<br>
<br>
<br>
流程控制<br>
<br>
BASH 中的基本流程控制语法<br>
BASH 中几乎含有 C 语言中常用的所有控制结构,如条件分支、循环等,下面逐一介绍。<br>
if...then...else<br>
if 语句用于判断和分支,其语法规则和 C 语言的 if 非常相似。其几种基本结构为:<br>
<br>
if [ expression ]<br>
then<br>
statments<br>
fi<br>
<br>
或者<br>
<br>
if [ expression ]<br>
then<br>
statments<br>
else<br>
statments<br>
fi<br>
<br>
或者<br>
<br>
if [ expression ]<br>
then<br>
statments<br>
else if [ expression ]<br>
then<br>
statments<br>
else<br>
statments<br>
fi<br>
<br>
或者<br>
<br>
if [ expression ]<br>
then<br>
statments<br>
elif [ expression ]<br>
then<br>
statments<br>
else<br>
statments<br>
fi<br>
<br>
值得说明的是如果你将 if 和 then 简洁的写在一行里面,就必须在 then 前面加上分号,如:if [ expression ]; then下面这个例子说明了如何使用 if 条件判断语句:<br>
<br>
#!/bin/bash<br>
<br>
if [ $1 -gt 90 ]<br>
then<br>
echo "Good, $1"<br>
elif [ $1 -gt 70 ]<br>
then<br>
echo "OK, $1"<br>
else<br>
echo "Bad, $1"<br>
fi<br>
<br>
exit 0<br>
<br>
上面例子中的 $1 是指命令行的第一个参数,这个会在后面的“BASH 中的特殊保留字”中讲解。<br>
<br>
for<br>
for 循环结构与 C 语言中有所不同,在 BASH 中 for 循环的基本结构是:<br>
<br>
for $var in [list]<br>
do<br>
statments<br>
done<br>
<br>
其中 $var 是循环控制变量,[list] 是 $var 需要遍历的一个集合,do/done 对包含了循环体,相当于 C 语言中的一对大括号。另外如果do 和 for 被写在同一行,必须在 do 前面加上 ";"。如: for $var in [list]; do 。下面是一个运用 for 进行循环的例子:<br>
<br>
#!/bin/bash<br>
<br>
for day in Sun Mon Tue Wed Thu Fri Sat<br>
do<br>
echo $day<br>
done<br>
<br>
# 如果列表被包含在一对双引号中,则被认为是一个元素<br>
for day in "Sun Mon Tue Wed Thu Fri Sat"<br>
do<br>
echo $day<br>
done<br>
<br>
exit 0<br>
<br>
注意上面的例子中,在 for 所在那行的变量 day 是没有加 "$" 符号的,而在循环体内,echo 所在行变量 $day 是必须加上 "$" 符号的。另外如果写成 for day 而没有后面的 in [list] 部分,则 day 将取遍命令行的所有参数。如这个程序:<br>
<br>
#!/bin/bash<br>
<br>
for param<br>
do<br>
echo $param<br>
done<br>
<br>
exit 0<br>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -