Be aware that there is an older, alternate syntax for “$(command)” that uses the backtick character “`“. This older form is compatible with the original Bourne shell (sh). I tend not to use the older form since I am teaching modern bash here, not sh, and besides, I think backticks are ugly. The bash shell fully supports scripts written for sh, so the following forms are equivalent:
$(command) `command`
把命令执行结果赋值给变量:
1
right_now=$(date +"%x %r %z")
常量
1 2
RIGHT_NOW=$(date +"%x %r %Z") TIME_STAMP="Updated on $RIGHT_NOW by $USER"
# First form test expression # Second form [ expression ]
test 命令和 if 命令一起完成 true / false 判断,当表达式为 true,test 以 0 退出;为 false,test 以 1 退出。
例如:
1 2 3 4 5
if [ -f .bash_profile ]; then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi
表达式“-f .bash_profile”表示 .bash_profile 是一个文件,若为 true,则执行 then 后的命令;否则执行 else 后的命令。
test 可以评估的表达式如下:
Expression
Description
-d file
True if file is a directory.
-e file
True if file exists.
-f file
True if file exists and is a regular file.
-L file
True if file is a symbolic link.
-r file
True if file is a file readable by you.
-w file
True if file is a file writable by you.
-x file
True if file is a file executable by you.
file1 -nt file2
True if file1 is newer than (according to modification time) file2
file1 -ot file2
True if file1 is older than file2
-z string
True if string is empty.
-n string
True if string is not empty.
string1 = string2
True if string1 equals string2.
string1 != string2
True if string1 does not equal string2.
不同的书写格式:
1 2 3 4 5 6 7 8 9 10 11 12 13
# Alternate form if [ -f .bash_profile ] then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi
# Another alternate form if [ -f .bash_profile ] then echo "You have a .bash_profile. Things are fine." else echo "Yikes! You have no .bash_profile!" fi
exit
exit 命令可以立即结束此脚本,并设置退出状态:
1
exit 0
test for superuser
id 命令可以查看当前用户信息:
1 2 3 4
[root@bhc004 ~]# id uid=0(root) gid=0(root) groups=0(root) [root@bhc004 ~]# id -u 0
1 2 3 4 5 6 7 8
if [ $(id -u) != "0" ]; then # >&2 输出到标准错误 echo "You must be the superuser to run this script" >&2 # 1 向操作系统表示脚本执行不成功 exit 1 else echo "superuser" fi
Watching your script
在第一行加 +x 监控脚本执行状态:
1
#!/bin/bash -x
或者,使用 set -x 和 set +x监控一段代码:
1 2 3 4 5 6 7 8 9 10 11
#!/bin/bash
number=1
set -x if [ $number = "1" ]; then echo "Number equals 1" else echo "Number does not equal 1" fi set +x
键盘输入和算术
用户交互。
read
从键盘输入并赋值给变量:
1 2 3 4 5
#!/bin/bash
echo -n "Enter some text > " read text echo "You entered: $text"
-n 使输入和字符串在同一行。read 有 -t、-s 等参数:
-t 表示在指定时间内获得响应,当无论用户是否输入都要继续执行时使用;
is 表示不显示输入的内容;当输入密码时使用;
1 2 3 4 5 6 7 8
#!/bin/bash
echo -n "Hurry up and type something! > " if read -t 3 response; then echo "Great, you made it in time!" else echo "Sorry, you are too slow!" fi
算术
使用双括号计算算术表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
#!/bin/bash
first_num=0 second_num=0
echo -n "Enter the first number --> " read first_num echo -n "Enter the second number -> " read second_num
echo "first number + second number = $((first_num + second_num))" echo "first number - second number = $((first_num - second_num))" echo "first number * second number = $((first_num * second_num))" echo "first number / second number = $((first_num / second_num))" echo "first number % second number = $((first_num % second_num))" echo "first number raised to the" echo "power of the second number = $((first_num ** second_num))"
括号内的变量不需要 $ 就可以引用,
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/bin/bash
number=0
echo -n "Enter a number > " read number
echo "Number is $number" if [ $((number % 2)) -eq 0 ]; then echo "Number is even" else echo "Number is odd" fi
流控制2
更过分支:
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/bin/bash
echo -n "Enter a number between 1 and 3 inclusive > " read character if [ "$character" = "1" ]; then echo "You entered one." elif [ "$character" = "2" ]; then echo "You entered two." elif [ "$character" = "3" ]; then echo "You entered three." else echo "You did not enter a number between 1 and 3." fi
使用 case 优化分支结构
case
case 语句格式如下:
1 2 3
case word in patterns ) commands ;; esac
改造如上语句:
1 2 3 4 5 6 7 8 9 10 11 12 13
#!/bin/bash
echo -n "Enter a number between 1 and 3 inclusive > " read character case $character in 1 ) echo "You entered one." ;; 2 ) echo "You entered two." ;; 3 ) echo "You entered three." ;; * ) echo "You did not enter a number between 1 and 3." esac
case 也可以匹配表达式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
#!/bin/bash
echo -n "Type a digit or a letter > " read character case $character in # Check for letters [[:lower:]] | [[:upper:]] ) echo "You typed the letter $character" ;;
# Check for digits [0-9] ) echo "You typed the digit $character" ;;
# Check for anything else * ) echo "You did not type a letter or a digit" esac
* 通常用来检测无效输入。
循环
while
1 2 3 4 5 6 7
#!/bin/bash
number=0 while [ "$number" -lt 10 ]; do echo"Number = $number" number=$((number + 1)) done
util
1 2 3 4 5 6 7
#!/bin/bash
number=0 until [ "$number" -ge 10 ]; do echo "Number = $number" number=$((number + 1)) done
home_space() { # Only the superuser can get this information
if [ "$(id -u)" = "0" ]; then echo "<h2>Home directory space by user</h2>" echo "<pre>" echo "Bytes Directory" du -s /home/* | sort -nr echo "</pre>" fi
# Check for required arguments if [ $# -ne 2 ]; then echo "usage: $0 directory_1 directory_2" 1>&2 exit 1 fi
# Make sure both arguments are directories if [ ! -d $1 ]; then echo "$1 is not a directory!" 1>&2 exit 1 fi
if [ ! -d $2 ]; then echo "$2 is not a directory!" 1>&2 exit 1 fi
# Process each file in directory_1, comparing it to directory_2 missing=0 for filename in $1/*; do fn=$(basename "$filename") if [ -f "$filename" ]; then if [ ! -f "$2/$fn" ]; then echo "$fn is missing from $2" missing=$((missing + 1)) fi fi done echo "$missing files missing"