1.环境准备
我们通过一个案例,持续的引入不同的概念。准备一个报告生成器的程序,显示系统的各种统计数据和状态,以HTML格式来生成报告。
#1.编写脚本
[root@REAL01 ~]#mkdir bin
[root@REAL01 ~]# vim ~/bin/sys_info_page
#!/bin/bash
#程序输出一个系统信息页
echo "<html>"
echo " <head>"
echo " <title>Page Title</title>"
echo " </head>"
echo " <body>"
echo " Page body"
echo " </body>"
echo "</html>"
# 2.增加执行权限并测试
[root@REAL01 ~]# chmod 755 bin/sys_info_page
[root@REAL01 ~]# cd bin
[root@REAL01 bin]# sys_info_page
<html>
<head>
<title>Page Title</title>
</head>
<body>
Page body
</body>
</html>
[root@REAL01 bin]#
在编写脚本时,应力求简洁明了,易于阅读和理解。上述脚本的另外一种写法,是不是很简洁。
#!/bin/bash
#程序输出一个系统信息页
echo "<html>
<head>
<title>Page Title</title>
</head>
<body>
Page body
</body>
</html>"
2. 添加数据
加入一个页标题,并为报告添加了正文标题
#!/bin/bash
#程序输出一个系统信息页
echo "<html>
<head>
<title>System Information Report</title>
</head>
<body>
<h1>System Information Report</h1>
</body>
</html>"
3.变量
创建名为title的变量并为其赋值System Information Report,可以利用参数扩展,将字符串置于多个位置。
#!/bin/bash
#程序输出一个系统信息页
title="System Information Report"
echo "<html>
<head>
<title>$title</title>
</head>
<body>
<h1>$title</h1>
</body>
</html>"
3.1 变量的命名规则
- 变量名可以包含字母,数字,下划线
- 变量名中的第一个字符只能是字母或下划线
- 变量名中不允许出现空格符和标点符号
“变量”一词暗示了其值可以改变,很多程序中,变量也是这么用的。常量和变量一样,有名称,也有值。两者的区别在于常量的值不能改变。Shell并不区分变量和常量,这种区分主要为了方便程序员理解。普遍的惯例使用大写字母表示变量。我们将脚本据此进行修改。
#!/bin/bash
#程序输出一个系统信息页
TITLE="System Information Report For $HOSTNAME"
echo "<html>
<head>
<title>$TITLE</title>
</head>
<body>
<h1>$TITLE</h1>
</body>
</html>"
借此机会在标题中加入了Shell变量HOSTNAME的值,该变量包含了主机的网络名称。
3.2 为变量赋值
变量的赋值方式如下:
variable=value
其中,variable是变量名,value是字符串。Shell并不在意变量赋值的数据类型,它将一切都视为字符串。
注意:在赋值操作中,变量名、赋值号、值这三者之间绝不能出现空白字符。值可以是什么?只要值能扩展成字符串
a=z #将字符串z赋给变量a
b=“a string” #内嵌空格符的字符串必须放入双引号中
c=“a string and KaTeX parse error: Expected 'EOF', got '#' at position 11: b" #̲赋值中包含的其他扩展(如,变量…(ls -l foo.txt)” #命令执行结果
e=$((5 * 7)) #算术扩展
f=“\t\ta string\n” #转义序列,例如制表符、换行符
在进行扩展时,变量名两边可以有选择地添加花括号。如果变量名由于其所处的环境而产生歧义,花括号就显得非常有用了。
[root@REAL01 bin]# filename="myfile"
[root@REAL01 bin]# cd test
[root@REAL01 test]# touch "$filename"
[root@REAL01 test]# mv "$filename" "$filename1"
mv: cannot move ‘myfile’ to ‘’: No such file or directory
操作失败的原因为Shell将mv命令的第二个参数解释为一个新变量,而新变量并不存在。解决方法如下
[root@REAL01 test]# mv "$filename" "${filename}1"
[root@REAL01 test]# ls
myfile1
将变量和命令替换置于双引号内,以此限制Shell对其进行单词分割操作,这是一种很好的做法。如果变量中可能包含文件名,双引号尤为重要。
基于上述讲到的内容,在报告中添加一些数据:报告生成的日期和时间以及创建者的用户名。
#!/bin/bash
#程序输出一个系统信息页
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME="$(date +"%x %r %Z")"
TIMESTAMP="Generated $CURRENT_TIME,by $USER"
echo "<html>
<head>
<title>$TITLE</title>
</head>
<body>
<h1>$TITLE</h1>
<P>$TIMESTAMP</p>
</body>
</html>"
3.3 here document
前面已经见了两种不同的文本输出方式,二者使用的都是echo命令,还有第三种称为here document(嵌入文档)。here document是另一种I/O重定向形式,利用它在脚本内嵌入文本快并将其发送至命令的标准输入,格式如下:
command << token
text
token
其中,command是能够接受标准输入的命令名称,token是一个字符串,用于标识嵌入文本的起止,接下来按照here document方法修改脚本
#!/bin/bash
#程序输出一个系统信息页
TITLE="System Information Report For $HOSTNAME"
CURRENT_TIME="$(date +"%x %r %Z")"
TIMESTAMP="Generated $CURRENT_TIME,by $USER"
cat << _EOF_
<html>
<head>
<title>$TITLE</title>
</head>
<body>
<h1>$TITLE</h1>
<P>$TIMESTAMP</p>
</body>
</html>
_EOF_
上述案例使用了cat和here document代替了先前的echo,选择字符串_EOF_(文件起止,end of file的缩写,命名惯例)作为token,标识嵌入文本的起止。注意,该字符串必须单独出现,所在行的末尾绝不能有空白字符。
here document的优势在哪?它其实和echo大同小异,只不过默认情况下,here document中的单引号和双引号不具备特殊含义。如下示例:
[root@REAL01 bin]# cat << _EOF_
> $foo
> "$foo"
> '$foo'
> \$foo
> _EOF_
a text
"a text"
'a text'
$foo
可以看出,Shell并没有例会引号,只将其作为普通字符对待。这就使在here document中随意使用引号。对我们的报告程序而言,非常方便。
所有能够接受标准输入的命令都可以使用here document。如下例:
#!/bin/bash
# download file srcipts
FTP_SERVER=1.1.1.1 FTP_PATH=/1/2/3 REMOTE_FILE=123.TXT
ftp -n <<- _EOF_
open $FTP_SERVER
user anonymous me@linxbox
cd $FTP_PATH
hash
get $REMOTE_FILE
bye
_EOF_
如果将重定向操作符从<<改为<<-,Shell就会忽略here document中每行文本开头的制表符(但不忽略空格符)。这样就可以对here document进行缩进,增强可读性。该特性有时候会有问题,因为很多编辑器以及程序员本身偏好在脚本中使用空格来代替制表符,实现缩进效果。