if-then 语句
# 如果 if 后面的 command 的退出状态码是 0,执行 then 后面的命令
if command
then
commands
fi
# 或者
if command; then
commands
fi
if grep $testuser /et/passwd
then
...
fi
#!/bin/bash
DIR="/media/cdrom"
if [ ! -e $DIR ]
then
mkdir -p $DIR
fi
if-then-else
if command
then
commands
else
commands
fi
if command
then
commands
elif command
then
commands
fi
#!/bin/bash
ping -c 3 -i 0.2 -W 3 $1 &> /dev/null
if [ $? -eq 0 ]
then
echo "Host $1 is On-line."
else
echo "Host $1 is Off-line."
fi
示例:
# 使用 if...elif
if grep $testuser /etc/passwd
then
echo "The user $testuser exists on this system."
elif ls -d /home/$testuser
then
echo "The user $testuser does not exist on this system."
echo "However, $testuser has a directory."
else
echo "The user $testuser does not exist on this system."
echo "However, $testuser does not have a directory."
fi
#!/bin/bash
read -p "Enter your score( 0-100): " GRADE
if [ $GRADE -ge 85 ] && [ $GRADE -le 100 ] ; then
echo "$GRADE is Excellent"
elif [ $GRADE -ge 70 ] && [ $GRADE -le 84 ] ; then
echo "$GRADE is Pass"
else
echo "$GRADE is Fail"
fi
test 命令
# test 命令没有命令的话,以非零的退出状态码退出
if test
then
echo "test command is ok."
else
echo "test command is false."
fi
# 可以使用 test 命令确定变量中是否有内容
my_variable="23"
if test $my_variable
then
echo "variable is not empty."
else
echo "variable is empty."
fi
使用方括号定义测试条件,第一个方括号之后和第二个方括号之前必须有空格:
- 数值比较
- 字符串比较
- 文件比较
数值比较
n1 -eq n2
n1 -ge n2
n1 -gt n2
n1 -le n2
n1 -lt n2
n1 -ne n2
# 方括号前后必须要有空格
# test 命令中不能使用浮点数
if [ $value1 -gt $value2 ]
then
echo "$value1 is greater than $value2"
elif [ $value1 -lt $value2 ]
then
echo "$value1 is less than $value2"
else
echo "$value1 is equal $value2"
fi
echo
FreeMem=`free -m | grep Mem: | awk '{print $4}'`
[ $FreeMem -lt 1024 ] && echo "Insufficient Memory"
字符串比较
str1 = str2
str1 != str2
str1 < str2
str1 > str2
-n str1
检查 str1 的长度是否非0
-z str1
检查 str1 的长度是否为0
注意,字符串顺序比较中:
- 大于号和小于号必须转义
- 大于和小于顺序和 sort 命令所采用的不同
在比较测试中,大写字母被认为是小于小写字母的。而 sort 命令相反。
比较测试中用的是标准的 ASCII 顺序。sort 命令使用的是系统的本地化语言设置中定义的排序顺序。对于英语,本地化设置指定了在排序顺序中小写字母出现在大写字母前。
if [ $USER != $testuser ]
then
...
fi
if [ $var1 \> $var2 ]
then
...
fi
[ $LANG != "en.US" ] && echo "Not en.US"
文件比较
-d file
测试文件是否为目录类型
-f file
判断是否为一般文件
-e file
测试文件是否存在
-r file
测试当前用户是否有权限读取
-w file
测试当前用户是否有权限写入
-x file
测试当前用户是否有权限执行
-O file
检查 file 是否存在并属于当前用户所有
-G file
检查 file 是否存在并且默认组与当前用户相同
-s file
检查 file 是否存在并非空
file1 -nt file2
file1 -ot file2
使用 -nt
或 -ot
比较文件之前,最后先检查文件是否存在:
# 文件不存在,返回 false
if [ badfile1 -nt badfile2 ]
then
echo "The badfile1 file is newer than badfile2"
else
echo "The badfile1 file is older than badfile2"
fi
# 结果是
The badfile1 file is older than badfile2
复合条件测试
[ condition1 ] || [ condition2 ]
[ condition1 ] && [ condition2 ]
[ ! $USER = root ] || echo "administrator"
双括号和双方括号
双括号里面可以进行算数运算。
双方括号里面可以进行字符串处理。
记住,不管是方括号还是双方括号,都需要有空格。而单括号的命令替换和双括号的算数运算,不需要有空格。
# 双括号里面不需要使用 $
if ((val1 ** 2 > 90))
then
# 赋值时 = 两边可以有空格
((val2 = val1 ** 2))
echo "The square of $val1 is $val2"
fi
# 方括号两边必需要有空格,模式匹配功能
if [[ $USER == x* ]]
then
echo "Hello $USER."
else
echo "Sorry, I do not know you."
fi
case 命令
case variable in
pattern1 | pattern2) commands1;;
pattern3) commands2;;
*) default commands;;
esac
注意结尾的双分号
case $USER in
xiaocan | barbara)
echo "Welcome, $USER"
echo "Please enjoy your visit.";;
testing)
echo "Special testing account.";;
jessica)
echo "Do not forget to log off when you're done.";;
*)
echo "Sorry, your are not allowed here";;
esac
#!/bin/bash
read -p "请输入一个字符,并按 Enter 键确认: " KEY
case "$KEY" in
[a-z]|[A-Z])
echo "您输入的是 字母。 "
;;
[0-9])
echo "您输入的是 数字。 "
;;
*)
echo "您输入的是 空格、功能键或其他控制字符。 "
esac
for 命令
for var in list
do
command
done
示例:
for test in Alabama Alaska Arizona Arkasas California
do
echo The next state is $test
done
# 不同于其他编程语言,在 for 循环结束后,也能够使用 test 变量
echo $test
# 对单引号转义,或者使用双引号包括它
for test in I don\'t know if "this'll" work
do
echo "word: $test"
done
# 使用双引号包括多个词汇
for test in Nevada "New Hampshire" "New York"
do
echo "City: $test"
done
# 字符串拼接的常用方法
list=$list" Connecticut"
# 怎么打印带有空格的字符呢?
files="states"
# 更新字段的分割符
IFS=$'\n'
for state in $(cat $files)
do
echo "Visit beautiful $state"
done
for 循环假定每个值都是空格分割的。使用 IFS
(内部字段分隔符 internal field separator)指定分隔符。
IFS.OLD=$IFS
IFS=$'\n'
# 之后再还原 IFS 的值
IFS=$IFS.OLD
IFS=:
# 换行符、冒号、分号、双引号
IFS=$'\n':;"
读取目录:
# 可以指定多个目录
for file in /Users/xiaocan/Documents/learn/shell-learn/* /home/rich/badtest
do
# 防止 file 名称有空格,所以添加引号
if [ -d "$file" ]
then
echo "$file is a directory."
elif [ -f "$file" ]
then
echo "$file is a file."
fi
done
批量 ping 主机:
#!/bin/bash
HLIST=$(cat ~/ipadds.txt)
for IP in $HLIST
do
ping -c 3 -i 0.2 -W 3 $IP &> /dev/null
if [ $? -eq 0 ] ; then
echo "Host $IP is On-line."
else
echo "Host $IP is Off-line."
fi
done
C 语言风格的 for 命令
# 括号两边的空格不是必需的
for (( i = 1; i <= 10; i++ ))
do
echo "The next number is $i"
done
echo
for (( a=1, b=10; a <= 10; a++, b--))
do
echo "$a - $b"
done
while 命令
while test command
do
commands
done
示例:
var1=10
while [ $var1 -gt 0 ]
do
echo $var1
var1=$(( var1 - 1 ))
done
echo
var1=5
# 多个测试命令
# 只有最后一个命令成立时才会停止。如果互换了下面两条命令的位置,就一直循环下去了
while echo $var1
[ $var1 -gt 0 ]
do
echo "This is inside the loop"
var1=$(( var1 - 1 ))
done
猜数字游戏:
猜数字游戏
#!/bin/bash
PRICE=$(expr $RANDOM % 1000)
TIMES=0
echo "商品实际价格为 0-999 之间,猜猜看是多少? "
while true
do
read -p "请输入您猜测的价格数目: " INT
let TIMES++
if [ $INT -eq $PRICE ] ; then
echo "恭喜您答对了,实际价格是 $PRICE"
echo "您总共猜 g $TIMES 次"
exit 0
elif [ $INT -gt $PRICE ] ; then
echo "太高了! "
else
echo "太低了! "
fi
done
until 命令
until test command
do
commands
done
示例:
var1=100
until [ $var1 -eq 0 ]
do
echo $var1
var1=$(( var1 - 25 ))
done
echo
# 使用多个测试命令
var1=100
until echo $var1
[ $var1 -eq 0 ]
do
echo Inside the loop.
var1=$(( var1 - 25 ))
done
break 和 continue
和编程语言中的 break 和 continue 类似,不同的是,在 shell 中它们后面可以跟一个数字,指定跳出的层数。
# 注意在 while 中使用 continue,下面的例子不会结束
var2=1
while [ $var2 -lt 15 ]
do
if [ $var2 -gt 5 ] && [ $var2 -lt 10 ]
then
continue
fi
echo "The value is $var2"
var2=$((var2+1))
done
处理循环的输出
可以在 done
命令之后添加一个处理命令。
# 在 done 后面使用管道或重定向命令
for state in "North Dakata" Connecticut Illinois Alabama Tennessee
do
echo "The state is $state"
done | sort
# 或者
# done > test.txt