脚本格式要求

  • 脚本以#!/bin/bash开头,使用什么解释器执行
  • 需要赋予脚本可执行权限(可选)

    脚本执行方式

  • 使用.以相对路径或者绝对路径执行脚本(需要可执行权限)(因为此处是需要当前的bash环境来执行,本身需要是可执行文件)

  • 使用sh XX.sh来执行脚本(不需要可执行权限)(因为这种启动方式只是将XX.sh作为一个参数传递给sh命令)
  • 使用.或者source执行脚本(不需要可执行权限)

    • 这里前两种方式本质上都是打开一个子shell来运行脚本,不影响父shell(全局shell)的环境。最后一种方式则是直接在父shell环境中去一条条解析执行,会对环境造成影响。

      shell变量

      系统变量

      Linux中存在着一些系统变量,比如$HOME$USER$PWD等,此时可以通过set命令来查看系统变量。
      image.png

      用户自定义变量

      基本示例

      当然,用户也可以自定义变量。

    • 定义变量:变量=值(等号两边不能有空格)

    • 撤销变量:unset 变量
    • 声明静态变量:readonly 变量(注意被静态声明的变量不能被unset)
      1. #!/bin/bash
      2. A="i am A value!"
      3. echo $A
      4. unset A
      5. echo "any A here? please answer me:$A"
      6. readonly B="i am B value!"
      7. echo $B
      8. unset B
      image.png
      可以看到第八行报错,B变量不能被unset

      自定义变量的一些规则

  • 变量名称可以以字母、数字和下划线组成,但是不能以数字开头

  • 等号两侧不能有空格
  • 变量名称一般习惯为大写

    将命令的返回值赋给变量

    例如ls命令,要想将该命令返回值赋给变量,就需要反引号符或者使用括号括起来。
    例如:
    A=ls /home`或者A=$(ls /home)`

    1. #!/bin/bash
    2. A=`ls /home/oosig`
    3. echo $A
    4. B=$(cat /home/oosig/shell/myshell.sh)
    5. echo $B

    image.png

    位置参数变量

    当执行一个脚本的时候,希望获取命令行的参数信息,就可以使用位置参数变量来获取相应信息。
    例如:
    ./XXX.sh 100 200
    基本语法:

    • $n:n为数字,$0代表命令本身,在上述例子中代表./XXX.sh$1-$9代表第一到第九个参数,十以上的参数需要用大括号包含,例如${10}
    • $*:这个变量代表着命令行中所有的参数,并把其看作一个整体
    • $@:这个变量也代表这命令行中所有的参数,不过它把每个参数区分对待
    • $#:这个变量代表命令行参数中所有参数的个数

image.png

预定义变量

有一些shell设计者本身已经定义好的变量,可以直接在shell脚本中使用:

  • $$:当前进程的进程号
  • $!:后台运行的最后一个进程的进程号
  • $?:最后一次执行的命令的返回状态。如果这个值为0,代表上一个命令正确执行;如果值不为0(具体是哪个数由命令自己决定),则证明上一个命令执行不正确。

    1. #!/bin/bash
    2. echo $$
    3. echo "echo AAAAAAAAAA" > anoshell.sh
    4. sh anoshell.sh &
    5. echo $!
    6. echo $?

    image.png

    环境变量

    在Linux中环境变量都在/etc/profile文件中定义的,在需要设置自己的全局变量的时候就需要在该文件的末尾加上自己的变量,并export
    即基本语法为:

  • export 变量名=变量值

  • source 配置文件(/etc/profile)

当然使用此方法也可以设置自己的局部环境,创建一个文件夹里面放置自己的变量环境,然后使用source命令。
image.png
首先touch一个profile,然后使用source命令加载这个文件。
image.png
image.png
环境变量设置完成。

注释

shell中的单行注释使用#符号,多行注释的时候,在开头使用:<<!,结尾使用!

  1. #!/bin/bash
  2. A=`ls /home/oosig`
  3. # echo $A
  4. :<<!
  5. B=$(cat /home/oosig/shell/myshell.sh)
  6. echo $B
  7. !
  8. echo $A

image.png

运算符

基本语法:

  • $((运算式))
  • $[运算式]
  • expr 操作数 操作符(注意操作符,例如+,-,,/ 等,有的是需要使用转义的,例如乘号,需要转义为*,还有括号等也需要转义)
    1. #!/bin/bash
    2. echo "the first cal way: \$(())"
    3. A=$(((2+3)*4))
    4. echo $A
    5. echo "the second cal way: \$[]"
    6. B=$[3*4]
    7. echo $B
    8. echo "the final cal way: expr"
    9. C=$(expr 3 + 2)
    10. D=$(expr $C \* 4)
    11. echo $D
    image.png
    不知道为什么$[]运算翻车了,可能Ubuntu这个版本的shell被改过了??
    使用服务器上的centos8是没有问题的。

    判断语句

    该判断的基本语句就是[ condition ],注意condition前后要有空格。非空返回true,可以使用$?验证。
    判断条件有-eq``-ne``-gt等,具体可见https://www.runoob.com/linux/linux-shell-basic-operators.html。 ```python

    !/bin/bash

    if [ “wx” = “wx” ] then echo “i am myself!” fi

if [ 22 -eq 22 ] then echo “22 is equal to 22!” fi

PATH=/home/oosig/shell/profile if [ -e $PATH ] then echo “the file $PATH exist!” fi

  1. ![image.png](https://cdn.nlark.com/yuque/0/2022/png/21358975/1656235039631-e7017673-0102-4661-9579-3c4549e36416.png#clientId=u66f02e45-0454-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=58&id=ua50a258f&margin=%5Bobject%20Object%5D&name=image.png&originHeight=72&originWidth=475&originalType=binary&ratio=1&rotation=0&showTitle=false&size=12549&status=done&style=none&taskId=u2993203f-ef1c-40d0-9b56-c58e85d7e0a&title=&width=380)
  2. <a name="K9N4I"></a>
  3. # 流程控制语句
  4. <a name="jfCxI"></a>
  5. ## if语句
  6. 基本使用语法:
  7. ```python
  8. if [ 条件判断式 ]
  9. then
  10. 程序
  11. fi
  12. ************或者************
  13. if [ 条件判断式 ]
  14. then
  15. 程序
  16. elif [ 条件判断式 ]
  17. then
  18. 程序
  19. fi

case语句

基本使用语法:

case $变量名 in
"值1")
    程序1
;;
"值2")
    程序2
;;
*)
    程序3(如果变量的值都不是以上的值,执行此程序)
;;
esac

示例:

#!/bin/bash
case $1 in
"1")
    echo "first day"
;;
"2")
    echo "second day"
;;
*)
    echo "third day"
;;
esac

image.png

for语句

有两种基本语法:

for 变量 in 值1 值2 值3
do
    程序
done
**********或者*********
for((初始值;循环控制条件;变量变化))
do
    程序
done

第一种语法示例:

#!/bin/bash
for i in "$*"
do
    echo "the num is : $i"
done

for j in "$@"
do
    echo "the num is : $j"
done

image.png
另外如果这里值,不带双引号,即"$*"->$*,也可以输出,关键是他会分开打印,很奇怪。

#!/bin/bash
for i in $*
do
    echo "the num is : $i"
done

for j in $@
do
    echo "the num is : $j"
done

image.png

第二种语法示例:

#!/bin/bash
SUM=0
for((i=1;i<=100;i++))
do
        SUM=$[$SUM + $i]
done
echo "sum for 1 to 100 is : $SUM"

image.png

while语句

基本语法:

while [ 条件判断式 ]
do
    程序
done
#!/bin/bash
SUM=0
i=1
while [ $i -le 100 ]
do
    SUM=$(($SUM + $i))
    i=$(($i + 1))
done
echo "cal result is : $SUM"

image.png

使用read语句读取从控制台的输入

这个就例如python中的input,c语言中的scanf一样,基本语法为:

read (选项) (变量)
选项:
-p 指定读取值的提示符;
-t 指定读取值的等待秒数,若没有在规定时间内输入就不再等待
#!/bin/bash
read -t 10 -p "input a number in ten seconds: " NUM
if [ $? -eq 0 ]
then
        echo "your input number is : $NUM"
fi

image.png

函数

系统函数

系统函数就是系统内部可以直接使用的函数。
image.png

#!/bin/bash
PATH_TEMP=/home/oosig/shell/myshell.sh
FILE_NAME=$(basename $PATH_TEMP)
echo $FILE_NAME
DIR_NAME=$(dirname $PATH_TEMP)
echo $DIR_NAME

image.png

用户函数

基本语法:

[ function ] funname [()]
{
    action;
    [return int;]
}
  • 可以带function fun() 定义,也可以直接fun() 定义,不带任何参数。
  • 参数返回,可以显示加:return 返回,如果不加,将以最后一条命令运行结果,作为返回值。
  • 在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例如,$1表示第一个参数,$2表示第二个参数等。$10 不能获取第十个参数,获取第十个参数需要${10}。当n>=10时,需要使用${n}来获取参数。
    #!/bin/bash
    function getsum()
    {
          return $[$1 + $2]
    }
    read -p "input your first num: " NUM1
    read -p "input your second num: " NUM2
    getsum $NUM1 $NUM2
    echo "the sum num is: $?"
    
    image.png
    注意,函数返回值在调用该函数后通过 $?来获得。