shell编程

什么是shell

1. Shell 是一个用C语言编写的应用程序,它是用户使用Linux的桥梁。

2. Shell既是一种命令语言,又是一种程序设计语言。

3. Shell是值一种应用程序,这个应用程序提供了一个界面,用户通过这个界面访问操作系统内核的服务。

脚本和环境

Shell脚本, 它是一种为shell编写的脚本程序。

Shell环境,使用一个能编写代码的文本编辑器 vi 和一个能解释执行的脚本解释器。如:/bin/bash。

Linux的Shell种类众多,常见的有:

1. /usr/bin/sh 或 /bin/sh   

2. /bin/bash (常用、默认)

3. /usr/bin/csh

...

作用

在Shell中,将许多命令写在一起,让用户很轻松的就能执行一个文件的Shell脚本,就能够一次执行多个命令。

基本格式

  • 创建文件:vi 脚本名字.sh

脚本第一行格式:

#!/bin/bash

符号#!用来指定该脚本文件的解析程序,这里使用的是bin目录下的bash解析器。

第一个脚本:vi hello.sh

#!/bin/bash

echo 'hello word'

脚本执行:

1. /bin/bash 脚本名  (推荐)

2. chmod +x 脚本名   -> ./脚本名

 注意事项:

  1. chmod + x file 加上执行权限,否则会提示无执行权限。
  2. 脚本后缀名可以任意修改,仍然可以正常运行。

Shell中的变量

变量:在程序运行过程中可以改变的量。

变量命名规则:

  1. 首个字符必须为字符(a-z,A-Z)。
  2. 中间不能有空格,可以使用下划线(_)。
  3. 不能使用标点符号。
  4. 不能使用bash里的关键字。

变量声明格式 : 变量名 = 变量值 

注:变量名和=之间不能有空格。

#!/bin/bash

you_name="qt"
echo $you_name  # 变量名前需要加$,或者 ${you_name},加花括号是为了帮助解释器识别变量的边界。

注意:在echo 字符串时,如果里面存在变量时,这个字符串要用""包裹,而不能使用'',
echo 'this is $you_name' # this is $you_name
echo "this is $you_name" # this is qt

只读变量

使用 readonly 命令可以将变量定义为只读变量。

#!/bin/bash
  
readonly you_name="qt"
echo $you_name  # 输出qt
you_name='tt'
echo $you_name  # 报错,并输出 qt

删除变量

使用 unset 命令可以删除变量

#!/bin/bash
you_name="qt"
echo $you_name  # qt
unset you_name
echo $you_name  # 空
# 注:当变量是 readonly 时,使用 unset 会报错

字符串操作

  1. 拼接字符串
    • #!/bin/bash
      name="hello"
      res="$name word"
      echo $res
  2. 获取字符串长度:${#变量名}
    • #!/bin/bash
      name="hello"
      res="$name word"
      echo ${#res}
  3. 提取子字符串:${变量名:截取字符的下标:截取的长度}
    • #!/bin/bash
      name="hello"
      res="$name word"
      echo ${res:1:4}
      

数组

定义:用括号代表数组,数组元素用“空格”符号分隔开。

形式:数组名=(值1 值2 ... 值n)

#!/bin/bash
num=(44 11 'hello' 'word')  # 定义数组并赋值,由此可见,数组中可以存放不同类型的数据
echo ${num[0]}  # 获取数组中下标为0的值
echo ${num[2]}  # 获取数组中下标为2的值
  1. 获取数组中所有的元素:${数组名[@]}
    • #!/bin/bash
      num=(44 11 'hello' 'word')
      echo ${num[@]}  # 获取所有元素
      echo ${num}  # 当不带下标时,默认输入第一个元素,44
      
  2. 获取数组的长度:${#数组名[@]}
    • #!/bin/bash
      num=(44 11 'hello' 'word')
      echo ${#num[@]}  # 4
      
  3. 获取数组中单个元素的长度:${#数组名[下标]}
    • #!/bin/bash
      num=(44 11 'hello' 'word')
      echo ${#num[1]}  # 2

数组练习:(直接复制运行即可,用于了解以上知识点)

#/bin/bash
a=(1 2 3 "word" 12.32)
echo "数组中的所有元素:${a[@]}"
echo "获取数组中的长度:${#a[@]}"
echo "获取数组中单个元素的长度:${#a[3]}"

注释

以“#”开头的行就是注释,会被解释器忽略。第一行的#是解释说明,并不是注释!

sh里没有多行注释,只能每行接一个#。

基本运算符

> 算术运算符

> 关系运算符

> 布尔运算符

> 逻辑运算符

> 字符串运算符

> 文件测试运算符

第一种运算方式:expr 是一款表达式计算工具,使用它能完成表达式的求值操作。

两个数相加(注意使用的是反引号` 而不是单引号 ')。

#!/bin/bash

exp=`expr 2 + 2`  # 表达式之间需要用空格
echo "sum: $exp"

第二种运算方式:$(()) 【推荐】

#!/bin/bash
a=20
b=10
c=$(($a * $b))
echo $c

优点:不需要考虑空格的问题,*运算时不需要进行转义
  1. 算术运算符
    • +    `expr $a + $b`      加
    • -     `expr $a - $b`  减
    • *     `expr $a * $b`  乘(使用这个字符时需要对它进行转义)
    • /     `expr $a / $b`  除
    • %   `expr $a % $b` 取余
    • =    `expr $a = $b`  等于
    • #/bin/bash
      a=10
      b=20
      echo "加:`expr $a + $b`"
      echo "减:`expr $a - $b`"
      echo "乘:`expr $a * $b`"
      echo "除:`expr $a / $b`"
      echo "取余:`expr $a % $b`"
      echo "相等:`expr $a = $b`"
      echo "恒等:`expr $a == %b`"
      # 算术运算符练习:(直接复制运行即可,了解以上知识点)
  2. 关系运算符

    关系运算符只支持数字,不支持字符串,除非字符串的值是数字。

假定变量 a =10, b=20;

  • -eq  检测两个数是否相等,相等返回true
  • -ne  检测两个数是否相等,不相等返回true
  • -gt  检测左边的数是否大于右边
  • -lt    检测左边的数是否小于右边
  • -ge  检测左边的数是否大于等于右边
  • -le   检测左边的数是否小于等于右边
  • #!/bin/bash
    read a
    if [ $a -lt 10 ]
    then
        echo "10 大于 $a"
    fi
    
    if [ $a -gt 10 ]
    then
        echo "10 小于 $a"
    fi
    if [ $a -eq 10 ]
    then
        echo "$a 等于 10"
    fi
    if [ $a -ne 10 ]
    then
        

  3. 布尔运算符

  • !  非运算
    • #!/bin/bash
      c=false
      if [ !$c ]
      then
          echo '相等'
      else
          echo '不相等'
      fi
      # 输出:相等
  • -o  或运算
    • #!/bin/bash
      a=10
      b=20
      if [ $a -gt 5 -o $b -lt 10 ]
      then
          echo 'true'
      else
          echo 'false'
      fi

      # 输出:true
  • -a  与运算 
    • #!/bin/bash
      a=10
      b=20
      if [ $a -gt 5 -a $b -lt 10 ]
      then
          echo 'true'
      else
          echo 'false'
      fi

      # 输出:false

4. 逻辑运算符

  • &&  逻辑与   如:[[$a -lt 100 && $b -gt 100]]
  • ||     逻辑或   如:[[$a -lt 100 || $b -gt 100]]

5. 字符串运算符

假定 a='abc'  b='dfg'

  • =  检测两个字符串是否相等
  • !=  检测两个字符串是否相等,不相等返回true。
  • -z  检测字符串长度是否为0,为0 返回true
  • -n  检测字符串长度是否为0,不为0返回true
  • str  检测字符串是否为空(null),不为空返回true,如:[$a]返回true

6. 文件测试运算符

文件测试运算符用于检测文件的各种属性。file可赋值为路径。如:file=/root/test.sh

  • -d file   检测文件是否是目录,如果是,则返回true。如:[ -d $file ] 返回true。
  • -f  file   检测是否是普通文件。如:[ -f $file ] 返回true。
  • -r  file   检测是否可读。如:[ -r $file ] 返回ture。
  • -w file   检测是否可写。
  • -x  file   检测是否可执行。
  • -s  file   检测文件是否为空(文件大小是否大于0)
  • -e  file   检测文件(目录)是否存在。

关于echo命令

作用:用于字符串的输出。格式: echo "字符串内容"

  1. 显示转义字符  echo ""It is a test""
  2. 显示变量
    • read 命令 从标准输入中读取一行,并把输入行的每个字段赋值给变量。
    • 格式: read  变量名 
    • #!/bin/bash
      echo -e "请输入str变量的值:c"
      read str
      echo "您输入的变量值为:$str"

      # 输入:hello word

      # 输出:hello word

  3. 显示换行
    • -e 开启转义
  4. 显示不换行
    • #!/bin/bash
      echo -e "it is good c"
      echo "testing"
      # 输出:it is good testing
  5. 显示结果定向至文件
    • #!/bin/bash
      echo
      "it is beautiful" > file # 将echo的结果定向保存到file文件中
      # 如果file中有文本,则覆盖里面的内容
      # 追加是:>>
  6. 显示命令执行结果
    • #!/bin/bash
      echo `date`
      # 输出:Sun Apr 5 11:52:27 CST 2022

      # 即:反引号`包裹的内容,会将他们作为命令执行。

练习:从终端中读取两个数据,判断其大小。

#!/bin/bash
echo -e "请输入第一个数字:c"
read n1
echo -e "请输入第二个数字:c"
read n2
if [ $n1 -eq $n2 ]
then
    echo "两数相等"
fi
if [ $n1 -lt $n2 ]
then
    echo "$n2 比 $n1 大"
fi
if [ $n1 -gt $n2 ]
then
    echo "$n1 比 $n2 大"
fi

常见的转义字符

注:在shell脚本中,除了转义符号之外,其他的转义操作都必须要借助于参数开启转义 -e

  •   后退(删除前一个字符)
  •   换行(回车)
  •   水平制表符
  •   清除前面的字符
  • c   不换行
  • \
  • "
echo "hello 
 word"
# 输出:hello 
 word

echo -e "hello 
 word"   # -e 开启转义
# 输出:
# hello
# word

关于printf命令

格式:printf  格式声明  与格式声明相对应的参数列表

格式声明由两部分组成:百分比符号(%)和指示符。

  • %d:data 数字 -- 对应位置参数必须是数字型
  • %s:str  字符串  --  对应位置参数必须是字符串
  • %c:char  字符  --  对应位置是显示相对应参数的第一个字符
  • %f:float  浮点  --  对应位置参数必须是浮点型
#!/bin/bash

printf "%-10s %-3.2f %-3c %2d
" name 0.12 aaa 20

# 注:
# %-10s:指一个宽度为10个字符(- 表示左对齐,没有则表示右对齐)
# 任何字符都会被显示在10个字符宽的字符内,如果不足则自动以空格填充,超过也会将内容全部显示出来
# %-3.2f:指格式化为小数,总共3位,其中 .2 表示保留两位小数

----------------
printf "%s %s %s " a b c d e f g h i
# 输出:当传递内容过多时,会根据格式进行自动划分分组显示。
# a b c
# d e f
# g h i

 关于test命令

Shell中的 test 命令用于检查某个条件是否成立,它可以进行数值、字符和文件三个方面的测试。

  • -eq   (相等)
  • -ne    (不等)
  • -gt   (大于)
  • -ge   (大于等于)
  • -lt   (小于)
  • -le   (小于等于)

数值举例:字符和文件测试相同,参考前面的字符、文件运算符。

#!/bin/bash
echo -e "请输入第一个数字:c"
read a
echo -e "请输入第二个数字:c"
read b

if test $a -eq $b
then
    echo "$a 和 $b 相等"
else
    echo "两者不相等"
fi

 练习:给定一个数字,判断奇偶数。

#!/bin/bash
echo -e "请输入第一个数字:c"
read a
if test `expr $a % 2` -eq 0
then
    echo "$a 是偶数"
else
    echo "$a 是奇数"
fi

 优先级问题:

“!”最高,“-a”次之,“-o”最低。(布尔运算符)

 if语句

格式:

#!/bin/bash

if [条件]  # 前面提到过:这里的[] 可以直接使用 test 进行条件判断
then
    语句
elif [条件]
then
    语句
else
    语句
fi

 练习:参加考试,90-100:奖励证书;70-90:奖励红花;60-70:奖励一巴掌;0-60:请离家出走;<0:输入错误。

#!/bin/bash
echo -e "请输入成绩:c"
read a
if test $a -ge 90 -a $a -le 100
then
    echo "奖励证书"
elif test $a -ge 70 -a $a -lt 90
then
    echo "奖励小红花"
elif test $a -ge 60 -a $a -lt 70
then
    echo "奖励一个大嘴巴子"
elif test $a -ge 0 -a $a -lt 60
then
    echo "请离家出走"
else
    echo "输入错误"
fi

条件判断(case ... esac 语句)

格式:

#!/bin/bash

case $变量 in
值1)
    ...
    ;;
值2)
    ...
    ;;
*)
    ...
    ;;
esac

循环(while ... do ... done)

格式

while ((判断条件))
do
    ...
done
# break 、continue

举例:

#!/bin/bash
read a
while (( $a >= 1 ))
do
    let "a--"  # let 命令,用于执行一个或多个表达式,变量计算中不需要加上$来表示变量
    echo "a的值为 $a"
    
done

练习:判断 0-100之间的偶数

#!/bin/bash

i=1
while (($i<=100))
do
    if [ $(($i%2)) == 0 ]
    then
        echo $i
    fi
    let "i++"
done

循环(for .. do ..done)

格式:

# 第一种格式
#!/bin/bash for ((初始值;条件;运算语句)) do ... dome

--------------
# 第二种格式
for 变量名 in 值1 值2 值3 ...
do
  ...
done

举例:

#!/bin/bash
for ((i=1;i<5;i++))
do
    echo $i
done

练习:统计1-100之间的奇数和偶数的个数

#!/bin/bash
j=0  # 奇数个数
o=0  # 偶数个数
for((i=1;i<=100;i++))
do
    if [ $(($i%2)) == 0 ]
    then
        let "o++"
    else
        let "j++"
    fi
done
echo "奇数个数为:$j"
echo "偶数个数为:$o"

 Shell函数的定义、执行与传参

格式1:

function 函数名 (){
  ...    
}

# 执行:函数名

格式2:

函数名 () {
  ...  
}
# 执行:函数名

注:

全局变量:在脚本内,函数体外声明的变量为全局变量

局部变量:在函数中声明的变量,需要用 local 关键词修饰

关于函数参数

在Shell中,调用函数时可以向其传递参数。在函数体内部,通过 $n 的形式来获取参数的值,例:$1 表示第一个参数,$2便是第二个参数。当 n>=10时,需要使用${n}来获取参数。 $# 统计当前参数总数,$* 获取的全部参数

例:

#!/bin/bash
function test() {
    echo "第一个参数为:$1"
    echo "第二个参数为:$2"
    echo "第十个参数为:${10}"
}
test 1 2 3 4 5 6 7 8 9 10 11

# 输出
#
第一个参数为:1
# 第二个参数为:2
# 第十个参数为:10

关于函数中的返回值

函数返回值在调用之后通过 $? 获得。

举例:

#!/bin/bash

function test() {
    echo -e "请输入第一个数:c"
    read a
    echo -e "请输入第一个数:c"
    read b
    return $(($a+$b))
}
test
echo "两数之和为:$?"

递归函数

自己调用自己

#!/bin/bash
function test() {
  echo "aa"  # 例子不好,无限循环,仅作参考
  test    
}
test

 ....持续更新

原文地址:https://www.cnblogs.com/RiverMap/p/12632873.html