Shell 脚本

Shell 脚本

Shell 编程跟 JavaScript、php 编程一样,只要有一个能编写的文本编辑器和一个能解释执行的脚本解释器就可以。

Bash 是大多数 Linux 系统默认的 Shell

一般情况下,不区分 Bourne Shell 和 Bourne Again Shell 所以,像 #! /bin/sh , 它同样可以改为 #! /bin/bash

#! 是告诉系统气候路径所指定的程序是解释此脚本呢的 Shell 程序

第一个 Shell 脚本

#! /bin/bash
echo "Hello Word!"

vim 创建 test.sh 文件中写入上述代码

分配可执行权限

chmod +x ./test.sh 或者 chmod 111 ./test.sh

执行脚本程序

./test.sh

获得输出 Hello Word!

Shell 变量

  • 定义变量不需要加美元符号 $

  • 命名只能字母,数字,下划线 且不能为数字开头

  • 不能使用 bash 关键字

  • 使用变量需要加美元符号 $

  • 使用时花括号 {} 可选,加不加都行

使用:

#! /bin/bash
my_name="PupilXiao"
echo $my_name
echo ${my_name}
  • 默认变量可以二次赋值,并且二次赋值的时候不需要使用 $
  • 使用 readonly 可以将变量设置为只读变量,只读变量不允许二次赋值,否则报错变量名: This variable is read only.
  • 使用 unset 命令可以删除变量,但是unset 不能删除只读变量,否则报错 cannot unset: readonly variable

使用:

#! /bin/bash
my_name="PupilYE"
echo $my_name
my_name="PupilXiao"
echo ${my_name}



readonly my_name
my_name="Pupil" # 这里会报错 my_name: This variable is read only



host="localhost"
echo $host
unset host
echo $host # 这里不会有任何输出

unset my_name # 这里报错 cannot unset: readonly variable
字符串

字符串是最常用最有用的数据类型,可以使用单引号,也可以使用双引号,还可以不用引号,但是建议使用双引号:双引号里面可以有变量,可以有转义字符

str=abcde
str='abcde'
str="abcde"  # 这三种定义方式都能通过
  • 字符串拼接(使用双引号),可以使用如下两种拼接方式

    my_name="PupilXiao"
    greeting="Hello! "$my_name"!"
    greeting="Hello! ${my_name}!"
    
  • 获取字符串长度

    str="abcd"
    echo ${#str} # #字符串 为字符串的长度,当 str 为数组时, #str <=> #str[0]
    
  • 获取子字符串

    str="Hello! PupilXiao!"
    echo ${str:1:4}   # 从下标为 1 开始截取 4 个字符,这里输出 ello
    
  • 查找子字符串

    str="Hello! PupilXiao!"
    echo `expr index "$str" io`  # 使用反引号 `,从 str 中查询 i 或者 o 从第几个单词开始,返回最先匹配到的序列,这里返回 5,对应第一个 o 位置
    
数组

shell 脚本中使用 () 来表示数组,元素之间使用 空格或者换行符 分割开

例: names=("PupilXiao" "YeZhiGang" "XiaoXiaoSheng")

或者:

names[0]="PupilXiao"
names[1]="YeZhiGang"
names[2]="XiaoXiaoSheng"
  • 读取数组,使用 @ 可以获取数组所有元素

    echo ${names[0]}

    echo ${names[@]}

  • 获取数组长度

    echo ${#names[@]} 或者 echo ${#names[*]}

  • 关联数组(效果类似 Map )

    declare -A name_age=(["PupilXiao"]="21" ["小玉"]="17" ["王亮"]="25")
    
    echo ${name_age["PupilXiao"]} # 获取到 21
    

注释

  • 单行注释

    # 单行注释直接使用 # 进行定义
    
  • 多行注释

    # 多行注释有两种
    
    :<<EOF
     这里可以编写注释
    EOF
    
    
    # EOF 也可使用其他字符代替
    
    :<<'
     这里编写注释
    '
    
    # 或者
    
    :<<!
     这里编写注释
    !
    

Shell 传参

在执行 Shell 脚本时,向脚本传递参数,脚本内获取参数的格式为:$n, n代表一个数字,指定第 n 个参数,从下标为 0 开始,其中第 0 个参数为文件名

#! /bin/bash
# 使用传参
# 假设调用 ./test.sh abc ab a
echo "Shell 脚本传递参数"
echo "第 0 个参数,文本名: $0"  # 第0个参数值 ./test.sh
echo "第 1 个参数,执行传递: $1" # 第1个参数值 abc
echo "第 2 个参数,执行传递: $2" # 第2个参数值 ab
echo "第 3 个参数,执行传递: $3" # 第3个参数值 a
echo "获取传参个数:$#"
echo "所有的传入参数: $*"
echo "获取执行脚本的进程ID号:$$"

Shell 运算符

  • 算数运算符

    + 加法 expr $a + $b
    - 减法
    * 乘法
    / 除法
    % 取余
    = 赋值
    == 相等 if [ $a == $b ]
    != 不等 if [ $a != $b ]
  • 关系运算符

    -eq 等于 if [ $a -eq $b]
    -ne 不等于 if [ $a -ne $b ]
    -gt 大于 if [ $a -gt $b]
    -lt 小于 if [ $a -lt $b]
    -ge 大于等于 if [ $a -ge $b]
    -le 小于等于 if [ $a -le $b]
  • 布尔运算符

    ! 非运算
    -o 或运算同逻辑运算 ||
    -a 与运算同逻辑运算 &&
  • 字符串运算符

    = 检测两个字符串是否相等 if [ $a = $b]
    != 检测两个字符串是否不等
    -z 检验字符串长度是否为0 if [ -z $a ]
    -n 检验字符串长度是否不为0 if [ -n $a ]
    $ 检测字符串是否不为空 if [ $a ]
  • 文件测试运算符

    -b file 检测是否块设备文件
    -c file 检测是否字符设备文件
    -d file 检测文件是否目录
    -f file 检测文件是否普通文件
    -g file 检测文件是否设置SGID位
    -k file 检测文件是否设置了粘着位
    -p file 检测文件是否有名管道
    -u file 检测文件是否设置SUID位
    -r file 检测文件是否可读
    -w file 检测文件是否可写
    -x file 检测文件是否可执行
    -s file 检测文件是否为空
    -e file 检测文件是否存在

echo 命令

  • 显示普通字符串

    echo "It is a test"

  • 显示转义字符

    echo "\"It is a test\""

  • 显示变量

    echo "$a Use variable"

  • 显示换行

    echo -e "ok! \n" -e 开启转义

  • 显示不换行

    echo -e "ok! \c"

  • 显示结果定向至文件

    echo "It is a test" > myfile

  • 原样输出字符串(不转义或取变量,使用单引号)

    echo '$name\"'

  • 显示命令执行结果,用反引号

    echo `date`
    

printf 命令

test 命令

Shell 流程控制

同其他语言不一样,Shell 命令中的流程控制语句不能为空

Shell 的流程控制语句很多都是 用反写来表示结束

  • if 流程控制语句,需要使用 fi 结尾

    • if fi

      if condition
      then 
      	command...    # 注意不能有 else,应为 else 不能为空
      fi
      
    • if else fi

      if condition
      then 
      	command... 
      else
      	command...
      fi
      
    • if else-if else fi

      if condition
      then 
      	command...
      elif condition2
      then
      	command...
      else
      	commandN
      fi
      
  • for 循环

    for name in PupilXiao YeZhiGang XiaoXiaoSheng
    do
    	echo "current element is ${name}"
    done
    
  • while 循环

    while condition
    do 
    	command...
    done
    
  • until 循环

    until condition
    do
    	command
    done
    
  • case ... esac => switch case

    read num
    case $num in
    	1) echo '你输入了 1'
    		;;    # 两个分号表示 break
    	2) echo '你输入了 2'
    		;;    
    	3) echo '你输入了 3'
    		;;
    	*) echo '你输入了其他的数组'
    		;;
    esac
    
  • 跳出循环

    • break
    • continue

Shell 函数

[ function ] funname [()]
{
	command...
	
	[return int]
}

使用实例

demoFun(){  # 定义函数
	echo "Test Function Of DemoFun!"
}
demoFun   # 执行函数,不传入任何参数


:<<EOF
	也可以使用 function 显示定义函数
function demoFun(){
	echo "显示定义函数"
}
EOF



# 定义有返回值和参数的 函数
demoFun(){
	echo "第一个参数 $1"
	return "你好,我是返回值"
}
demoFun
echo "函数返回值 $? " # 函数返回值在调用函数后使用 $? 获得


Shell 输入输出重定向

command > file 输出重定向到 file
command < file 输入重定向到 file
command >> file 输出以追加的方式重定向到 file
n > file 文件描述符为 n 的文件重定向到file
n >> file 以追加的方式重定向
n >& m 输出文件 m 和 n 合并
n <& m 将输入文件 m 和 n 合并
<< tag 将开始标记 tag 和结束标记 tag 之间的内容作为输入

Shell 文件包含

posted @ 2023-04-14 16:24  PupilXIao  阅读(24)  评论(0编辑  收藏  举报