返回

shell 脚本入门笔记

被迫学习 shell

基本格式

#!/bin/bash
echo 'Hello World'

#!/bin/bash:脚本的第一行声明了脚本的解释器,对于 shell 脚本解释器通常为 /bin/bash,当然如果是 python 脚本也可以写成 #!/bin/python

第一行之后的所有内容就是具体的命令,变量以及函数了。

运行方式

# 使用脚本中声明的解释器解释执行,如果未声明则使用当前 shell 解释执行。
./script.sh

# 使用指定的解释器执行
# 使用 /bin/sh 解释执行
sh script.sh
# 使用 /bin/bash 解释执行
bash script.sh

变量

永久环境变量

本质属于文件,对于所有 shell 均可访问。

临时环境变量

只允许当前 shell 以及其子 shell 访问。一般通过 export 来设置。

shellexport VAR_NAME=alice

临时变量

仅仅允许当前 shell 访问。直接在声明即可。shell 脚本中不存在高级语言中局部变量这个概念,也就是 shell 脚本中任何位置声明的变量均为全局变量。

shellvar1=1

特殊变量

变量 含义
$0 当前脚本的文件名。
$n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是,第二个参数是2。
$# 传递给脚本或函数的参数个数。
$* 传递给脚本或函数的所有参数。
$@ 传递给脚本或函数的所有参数。被双引号(” “)包含时,与 $* 稍有不同,下面将会讲到。
$? 上个命令的退出状态,或函数的返回值。
$$ 当前Shell进程ID。对于 Shell 脚本,就是这些脚本所在的进程ID。

$* 和 $@

这两个变量在不使用双引号包裹的时候完全一样

#!/bin/bash
function foo()
{
    for var in $*
    do
        # -e 表示启用转义字符
        echo -e "$var\n"
    done
}

foo 1 2 3 4 5
#!/bin/bash
function foo()
{
    for var in $@
    do
        # -e 表示启用转义字符
        echo -e "$var\n"
    done
}

foo 1 2 3 4 5

上面两个脚本的执行结果一样:

1
2
3
4
5

但是一旦被双引号包裹就不一样了

#!/bin/bash
function foo()
{
    for var in "$*"
    do
        # -e 表示启用转义字符
        echo -e "$var\n"
    done
}

foo 1 2 3 4 5

输出为 1 2 3 4 5[换行]

#!/bin/bash
function foo()
{
    for var in $@
    do
        # -e 表示启用转义字符
        echo -e "$var\n"
    done
}

foo 1 2 3 4 5

输出结果依旧为

1
2
3
4
5

基础算数运算

可以进行简单的四则运算。但是 bash 不支持浮点运算,所以除法会直接截断小鼠部分。同时由于 * 在 shell 中有特殊的含义,所以必须使用 \ 进行转义才能使用乘法。

# 结果为 3
expr 1 + 2

# 结果为 -1
expr 1 - 2

# 结果为 6
expr 2 \* 3

# 结果为 2
expr 5 / 2

条件判断

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。 test 可以用 [] 代替,如 test $var1 -eq $var2[ $var1 -eq $var2 ] 等价。但是不允许省略空格,也就是说 [$var1 -eq $var2] 是错的。

数字比较

参数 作用 举例
-eq 相等则为真 test $var1 -eq $var2
-ne 不等则为假 test $var1 -ne $var2
-gt 大于则为真 test $var1 -gt $var2
-ge 大于等于则为真 test $var1 -ge $var2
-lt 小于则为真 test $var1 -lt $var2
-le 小于等于则为真 test $var1 -le $var2

字符串比较

参数 作用 举例
= 等于则为真 test $str1 = $str2
!= 不等则为真 test $str1 != $str2
-z 字符串长度为零则为真 test -z $str1
-n 字符串长度不为零则为真 test -n $str1

文件判断

参数 作用 举例
-e 如果文件存在则为真 test -e $filename
-r 如果文件存在且可读则为真 test -r $filename
-w 如果文件存在且可写则为真 test -w $filename
-x 如果文件存在且可执行则为真 test -x $filename
-s 如果文件存在且至少有一个字符则为真 test -s $filename
-d 如果文件存在且为目录则为真 test -d $filename
-f 如果文件存在且为普通文件则为真 test -f $filename
-c 如果文件存在且为字符型特殊文件则为真 test -c $filename
-b 如果文件存在且为块特殊文件则为真 test -b $filename

流程控制

if

语法

if boolean ; then
    # TODO
fi

if boolean
then
   # TODO
fi

举例

shell 代码

#!/bin/bash
if [ 1 -eq 2 ] ; then
    echo '1 == 2'
fi

等价 C 代码

if (1 == 2) {
    printf("1 == 2");
}

if···else

语法

if boolean ; then
    # TODO
else
    # TODO
fi

if boolean
then
    # TODO
else
    # TODO
fi

举例

shell 代码

#!/bin/bash
if [ 1 -eq 2 ] ; then
    echo '1 == 2'
else
    echo '1 != 2'
fi

等价 C 代码

if (1 == 2) {
    printf("1 == 2");
} else {
    printf("1 != 2");
}

if···elif

if boolean ; then
    # TODO
elif boolean ; then
    # TODO
fi

if boolean
then
    # TODO
elif boolean
then
    # TODO
fi

for

语法

for var in item0 item1 item2 ....
do
    # TODO
done

举例

#!/bin/bash
for num in 1 2 3 4 5
do
    # -e 代表开启字符转义
    echo -e "${num}\n"
done

结果

1
2
3
4
5

while

语法

while boolean
do
    # TODO
done

举例

shell 代码

#!/bin/bash
max=6
num=0
while [ $num -lt $max ]
do
    echo -e "${num}\n"
    num=`expr $num + 1`
done```

等价 C 代码

```shell
int max = 6, num = 0;
while (num < max) {
    printf("%d\n", num);
    num += 1;
}```

## 函数

### 语法

```shell
# 声明函数(无论有无参数括号内均为空)
function name()
{
    # TODO
    return value
}

# 调用参数,后面跟上若干的参数
name 1 2 3 ...

其中 function 可以省略,return 也可以省略,返回值默认为最后一条指令的执行结果,return 只允许接数字,且范围为$[0,255]$。

举例

#!/bin/bash

function sum()
{
    ret=0
    for num in $@
    do
            ret=`expr $ret + $num`
    done
    return $ret
}

# 计算 1 + 2 + 3
sum 1 2 3
echo $?

双引号、单引号和反引号

双引号

双引号中允许使用变量。

#!/bin/bash
str=World
echo "Hello $str"

结果为 Hello World。

单引号

单引号中的内容将原文输出,但是不对转义符生效。

#!/bin/bash
str=World
echo 'Hello $str'

结果为 Hello $str。

反引号

会将反引号中的命令作为返回值

#!/bin/bash
list=`ls`
echo $list

结果是当前目录中的文件。

$()

$() 类似函数一样让我们将某个命令赋值给某个变量,当使用该变量时才会执行对应的命令并将返回值作为变量的值。

(())

扩展运算,支持了 C 语言大部分的写法。

  • 在双括号结构中,所有表达式可以像c语言一样,如:a++b-- 等。
  • 在双括号结构中,所有变量可以不加入:$ 符号前缀。
  • 双括号可以进行逻辑运算,四则运算。
  • 双括号结构 扩展了 forwhile, if 条件测试运算
  • 支持多个表达式运算,各个表达式之间用 , 分开。
#!/bin/bash
num=1
((num++))
((num=num+1+2-3*4/5))
((num+=1+2-3*4/5))

# 打印 [0...9]
for((i=0;i<10;i++))
do
    echo -e "$((i))\n"
done

# 如果 5 能被 2 整除则输出 true,反之输出 false
if ((5%2==0)) ; then
    echo 'true'
else
    echo 'false'
本博客所有文章除特别声明外均默认为原创。除特别声明外,本站所有的原创文章均采用 CC BY-NC-SA 4.0 许可协议。
comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy