大多数的 Linux 发行版会配置 PATH 变量,让其包含 一个位于用户家目录下的 bin 目录,从而允许用户能够执行他们自己的程序。所以如果我们创建了 一个 bin 目录,并把我们的脚本放在这个目录下,那么这个脚本就应该像其它程序一样开始工作了。如果这个 PATH 变量不包含这个目录,我们能够轻松地添加它,通过在我们的.bashrc 文件中包含下面 这一行文本:
而不是在 /bin 或 /usr/bin 目录。这些目录都是由 Linux 文件系统层次结构标准指定,只包含由 Linux 发行商所提供和维护的文件。
语法
通过使用行继续符(反斜杠-回车符序列)和缩进,这个复杂命令的逻辑会被更清楚地描述给读者。
多行字符串
编写的程序是一个报告生成器。它会显示系统的各种统计数据和它的状态,并将产生 HTML 格式的报告。
1 2 3 4 5 6 7 8 9 10
#!/bin/bash # Program to output a system information page echo"<HTML> <HEAD> <TITLE>System Information Report</TITLE> </HEAD> <BODY> <H1>System Information Report</H1> </BODY> </HTML>"
#!/bin/bash # Program to output a system information page title="System Information Report" # 惯例是指定大写字母来表示常量,小写字母表示真正的变量。 TITLE="System Information Report For $HOSTNAME" declare -r TITLE=”Page Title” # -r(只读)选项的内部命令declare来强制常量的不变性.随后所有给 TITLE 的赋值都会被 shell 阻止 CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" echo"<HTML> <HEAD> <TITLE>$TITLE</TITLE> </HEAD> <BODY> <H1>$TITLE</H1> <P>$TIME_STAMP</P> </BODY> </HTML>"
Here Documents与echo
echo 命令通过有引号的字符串可以输入,here document 或者 here script也可以实现echo 的功能。一个 here document 是另外一种 I/O 重定向形式,我们 在脚本文件中嵌入正文文本,然后把它发送给一个命令的标准输入。它这样工作:
#!/bin/bash # Program to output a system information page TITLE="System Information Report For $HOSTNAME" CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" cat << _EOF_ <HTML> <HEAD> <TITLE>$TITLE</TITLE> </HEAD> <BODY> <H1>$TITLE</H1> <P>$TIME_STAMP</P> </BODY> </HTML> _EOF_
正如我们所见到的,shell 根本没有注意到引号。它把它们看作是普通的字符。这就允许在一个 here document 中可以随意的嵌入引号。对于我们的报告程序来说,这将是非常方便的。Here documents 可以和任意能接受标准输入的命令一块使用。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#!/bin/bash # Script to retrieve a file via FTP FTP_SERVER=ftp.nl.debian.org FTP_PATH=/debian/dists/lenny/main/installer-i386/current/images/cdrom REMOTE_FILE=debian-cd_info.tar.gz ftp -n << _EOF_ open $FTP_SERVER user anonymous me@linuxbox cd $FTP_PATH hash get $REMOTE_FILE bye _EOF_ ls -l $REMOTE_FILE
如果我们把重定向操作符从 “<<” 改为 “<<-”,shell 会忽略在此 here document 中开头的 tab 字符。 这就能缩进一个 here document,从而提高脚本的可读性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
#!/bin/bash # Script to retrieve a file via FTP FTP_SERVER=ftp.nl.debian.org FTP_PATH=/debian/dists/lenny/main/installer-i386/current/images/cdrom REMOTE_FILE=debian-cd_info.tar.gz ftp -n <<- _EOF_ open $FTP_SERVER user anonymous me@linuxbox cd $FTP_PATH hash get $REMOTE_FILE bye _EOF_ ls -l $REMOTE_FILE
#!/bin/bash echo -n "Please enter an integer -> " # -n 选项会删除输出结果末尾的换行符,来显示提示信息,然后使用read来读入变量 int 的数值。 read int if [[ "$int" =~ ^-?[0-9]+$ ]]; then if [ $int -eq 0 ]; then echo "$int is zero." else if [ $int -lt 0 ]; then echo "$int is negative." else echo "$int is positive." fi if [ $((int % 2)) -eq 0 ]; then echo "$int is even." else echo "$int is odd." fi fi else echo "Input value is not an integer." >&2 exit 1 fi
读取多个参数
1 2 3 4 5 6 7 8 9
#!/bin/bash # read-multiple: read multiple values from keyboard echo -n "Enter one or more values > " read var1 var2 var3 var4 var5 echo"var1 = '$var1'" echo"var2 = '$var2'" echo"var3 = '$var3'" echo"var4 = '$var4'" echo"var5 = '$var5'"
#!/bin/bash # read-validate: validate input invalid_input () { echo"Invalid input '$REPLY'" >&2 exit 1 } read -p "Enter a single item > " # input is empty (invalid) [[ -z $REPLY ]] && invalid_input # input is multiple items (invalid) (( $(echo $REPLY | wc -w) > 1 )) && invalid_input # is input a valid filename? if [[ $REPLY =~ ^[-[:alnum:]\._]+$ ]]; then echo"'$REPLY' is a valid filename." if [[ -e $REPLY ]]; then echo"And file '$REPLY' exists." else echo"However, file '$REPLY' does not exist." fi # is input a floating point number? if [[ $REPLY =~ ^-?[[:digit:]]*\.[[:digit:]]+$ ]]; then echo"'$REPLY' is a floating point number." else echo"'$REPLY' is not a floating point number." fi # is input an integer? if [[ $REPLY =~ ^-?[[:digit:]]+$ ]]; then echo"'$REPLY' is an integer." else echo"'$REPLY' is not an integer." fi else echo"The string '$REPLY' is not a valid filename." fi
#!/bin/bash # read-menu: a menu driven system information program clear echo" Please Select: 1. Display System Information 2. Display Disk Space 3. Display Home Space Utilization 0. Quit " read -p "Enter selection [0-3] > " if [[ $REPLY =~ ^[0-3]$ ]]; then if [[ $REPLY == 0 ]]; then echo"Program terminated." exit fi if [[ $REPLY == 1 ]]; then echo"Hostname: $HOSTNAME" uptime exit fi if [[ $REPLY == 2 ]]; then df -h exit fi if [[ $REPLY == 3 ]]; then if [[ $(id -u) -eq 0 ]]; then echo"Home Space Utilization (All Users)" du -sh /home/* else echo"Home Space Utilization ($USER)" du -sh $HOME fi exit fi else echo"Invalid entry." >&2 exit 1 fi
$ posit-param $* : $1 = word $2 = words $3 = with $4 = spaces "$*" : $1 = word words with spaces $2 = $3 = $4 = $@ : $1 = word $2 = words $3 = with $4 = spaces "$@" : $1 = word $2 = words with spaces $3 = $4 =
通过我们的参数,$* 和 $@ 两个都产生了一个有四个词的结果:
1 2 3 4 5
word words with spaces "$*" produces a one word result: "word words with spaces" "$@" produces a two word result: "word" "words with spaces"