Shell命令(2)

26 7月

源码在这里Github(forked from shehaodan/full-shell-demo)

  • 数学计算
  • 条件语句
  • 循环语句
  • 函数

数学计算

不能直接进行算数运算,要用数学计算(( ))命令,用$(( ))获取表达式的结果

echo 2+8    # 输出 2+8 被当做字符串处理了

a=$((10+66))
b=$((a-15))
c=$((a+b))      # 注意,类似 c=((a+b)) 这样的写法是错误的,不加$就不能取得表达式的结果
echo $c         # 137
echo $((c+13))  # 150

也可以使用let用于整数运算,和(())类似。如果let后面的表达式中有例如|等特殊字符,需要用双引号” “或者单引号’ ‘将表达式包围起来。

echo let 1+2  # 错误,echo会把 let a+b作为一个字符串输出

let c=1+2
echo ${c}     # 3

条件语句

if语法:

if  condition1
then
   statement1
elif condition2
then
    statement2
elif condition3
then
    statement3
else
    statement4
fi

test是内置命令,用来检测某个条件是否成立。通常和if语句一起使用,大部分if语句都依赖test。test 命令有很多选项,可以进行数值、字符串和文件三个方面的检测。

test expression  # 当expression成立时,退出状态为 0,否则为非 0 值
[ expression ]   # 简写,注意[]和expression之间的空格

与文件类型相关的test选项:

-b filename:判断文件是否存在,并且是否为块设备文件
-c filename:判断文件是否存在,并且是否为字符设备文件
-d filename:判断文件是否存在,并且是否为目录文件
-e filename:判断文件是否存在
-f filename:判断文件是否存在,井且是否为普通文件
-L filename:判断文件是否存在,并且是否为符号链接文件
-p filename:判断文件是否存在,并且是否为管道文件
-s filename:判断文件是否存在,并且是否为非空
-S filename:判断文件是否存在,并且是否为套接字文件

与文件权限相关的test选项:

-r filename:判断文件是否存在,并且是否拥有读权限
-w filename:判断文件是否存在,并且是否拥有写权限
-x filename:判断文件是否存在,并且是否拥有执行权限
-u filename:判断文件是否存在,并且是否拥有 SUID 权限
-g filename:判断文件是否存在,并且是否拥有 SGID 权限
-k filename:判断该文件是否存在,并且是否拥有 SBIT 权限

与文件比较相关的test选项:

filename1 -nt filename2:判断 filename1 的修改时间是否比 filename2 的新
filename1 -ot filename2:判断 filename1 的修改时间是否比 filename2 的旧
filename1 -ef filename2:判断 filename1 是否和 filename2 的 inode 号一致,可以理解为两个文件是否为同一个文件。这个判断用于判断硬链接是很好的方法

与数值比较相关的test选项(test只能用来比较整数,小数相关的比较还得依赖bc命令):

num1 -eq num2:判断 num1 是否和 num2 相等
num1 -ne num2:判断 num1 是否和 num2 不相等
num1 -gt num2:判断 num1 是否大于 num2
num1 -lt num2:判断 num1 是否小于 num2
num1 -ge num2:判断 num1 是否大于等于 num2
num1 -le num2:判断 num1 是否小于等于 num2

与字符串相关的test选项:

-z str:判断字符串 str 是否为空
-n str:判断字符串 str 是否为非空
str1 = str2,str1 == str2:=和==是等价的,都用来判断 str1 是否和 str2 相等
str1 != str2:判断 str1 是否和 str2 不相等
str1 \> str2:判断 str1 是否大于 str2。\>是>的转义字符,这样写是为了防止>被误认为成重定向运算符
str1 \< str2:判断 str1 是否小于 str2。同样,\<也是转义字符

与逻辑运算相关的test选项:

expression1 -a expression:逻辑与
expression1 -o expression2:逻辑或
!expression:逻辑非

[[ ]]是内置关键字,和test命令类似,也用来检测某个条件是否成立。支持正则表达式:

[[ expression ]] # 注意[[ ]]和expression之间的空格,这两个空格是必须的,否则会报错

#!/bin/bash
read tel
if [[ $tel =~ ^1[0-9]{10}$ ]]
then
    echo "你输入的是手机号码"
else
    echo "你输入的不是手机号码"
fi

case in语句:

case expression in
    pattern1)
        statement1
        ;;
    pattern2)
        statement2
        ;;
    ……
    *)
        statement
esac


#!/bin/bash
printf "Input integer number: "
read num
case $num in
    1)
        echo "Monday"
        ;;
    2)
        echo "Tuesday"
        ;;
    3)
        echo "Wednesday"
        ;;
    4)
        echo "Thursday"
        ;;
    5)
        echo "Friday"
        ;;
    6)
        echo "Saturday"
        ;;
    7)
        echo "Sunday"
        ;;
    *)
        echo "error"
esac

#!/bin/bash
printf "Input a character: "
read -n 1 char
case $char in
    [a-zA-Z])
        printf "\nletter\n"
        ;;
    [0-9])
        printf "\nDigit\n"
        ;;
    [,.?!])
        printf "\nPunctuation\n"
        ;;
    *)
        printf "\nerror\n"
esac

循环语句

while语句:

while condition
do
    statements
done

until语句:当判断条件不成立时才进行循环,一旦判断条件成立,就终止循环

until condition
do
    statements
done

for语句:

# 形式1--c语言风格
for((exp1; exp2; exp3))
do
    statements
done

# 形式2--python风格 --for-in
for variable in value_list
do
    statements
done

select in:用来增强交互性,它可以显示出带编号的菜单,用户输入不同的编号就可以选择不同的菜单,并执行不同的功能。select是无限循环(死循环),输入空值,或者输入的值无效,都不会结束循环,只有遇到break,或者按下 Ctrl+D 组合键才能结束循环。

select variable in value_list
do
    statements
done

#!/bin/bash
echo "What is your favourite OS?"
select name in "Linux" "Windows" "Mac OS" "UNIX" "Android"
do
    echo $name
done
echo "You have selected $name"

break,continue:break用来结束所有循环。continue用来结束本次循环

break n     # n表示跳出循环的层数,如果省略n,则表示跳出当前的整个循环。

continue n

函数

函数在定义时可以不指明参数,但是在调用时却可以传递参数,并且给它传递什么参数它就接收什么参数。函数也不限制定义和调用的顺序,你可以将定义放在调用的前面。

返回值只能是一个介于 0~255 之间的整数,其中只有 0 表示成功,其它值都表示失败。如果函数体中没有return语句,那么使用默认的退出状态,也就是最后一条命令的退出状态。

#1 --> 普通写法
function name() {
    statements
    [return value]
}

#2 --> 简化写法
name() {
    statements
    [return value]
}

name                      # 调用函数
name param1 param2 param3 # 多个参数之间以空格分隔

如何得到函数的返回值:一种是借助全局变量,将得到的结果赋值给全局变量。一种是在函数内部使用 echo、printf 命令将结果输出,在函数外部使用$()或者“捕获结果。

#!/bin/bash
function getsum() {
    local sum=0      # 局部变量
    for((i=$1; i<=$2; i++)); do
        ((sum+=i))
    done

    echo $sum
    return $?
}
read m
read n
total=$(getsum $m $n)       # $()捕获了第一个echo的输出结果,它并没有真正输出到终端上
echo "The sum is $total"    # 输入5,10,将打印出45

发表评论

电子邮件地址不会被公开。 必填项已用*标注