shell脚本语法详解

时间:2024-10-25 07:13:05

目录

shell语法基础

指定shell解析器

注释

运行

 变量

定义变量

引用变量

清除变量值

从键盘获取值

输入单值

 添加输入提示语

读取多值

​编辑

定义只读变量

环境变量

设置环境变量与查看环境变量

特殊变量

三种引号的作用与区别

小括号与大括号

参数传递

位置参数传递

选项参数传递

获取参数相关信息

 其余预设变量

字符串处理

条件测试

文件测试

字符串测试

数值测试

控制语句

逻辑语句

条件语句

if语句

case语句

循环语句

for循环

while循环

函数

函数定义

函数的调用与返回

文件导入


shell语法基础

指定shell解析器

#!/bin/bash

#!用来声明脚本由什么shell解释,否则使用默认shell

shell终端有多种,我们大部分用的是sh或者bash,其中sh是最原始的shell,而bash不完全兼容sh,查看系统可用的shell终端可用以下命令

 vim /etc/shells
/bin/sh
/bin/bash
/bin/rbash
/bin/dash
/usr/bin/tmux
/usr/bin/screen

注释

#

运行

shell脚本有三种执行方式

  • ./xxx.sh
    • ./xxx.sh :先按照 文件中#!指定的解析器解析

      如果#!指定指定的解析器不存在 才会使用系统默认的解析器

  • bash xxx.sh
    • bash xxx.sh:指明先用bash解析器解析

      如果bash不存在 才会使用默认解析器

  • . xxx.sh 
    •  直接使用默认解析器解析(不会执行第一行的#!指定的解析器)但是第一行还是要写的

三种执行情况:

打开终端就会有以后个解释器,我们称为当前解释器

我们指定解析器的时候(使用 ./xxx.sh 或 bash xxx.sh)时会创建一个子shell解析 脚本

 变量

定义变量

变量名=变量值
如:num=10

引用变量

$变量名

清除变量值

unset 

从键盘获取值

read命令可以从键盘获取值

输入单值

#!/bin/bash
echo "--------"
read data
echo "data=$data"

运行结果

 添加输入提示语

使用read命令的-p选项可以添加输入提示语

#!/bin/bash
echo "--------"
read -p "please input the value of data:" data
echo "data=$data"

读取多值

#!/bin/bash
read -p "please input the value of data1 and data2 >>> " data1 data2
echo "data1 is ${data1} and the data2 is ${data2}"

注意,输入时以空格作为分隔符,运行结果如下: 

定义只读变量

readonly关键字可标识一个变量为只读变量 

#!/bin/bash
readonly num=10
echo "num=$num"
num=20
echo "after num=$num"

环境变量

设置环境变量与查看环境变量

创建一个test.sh脚本,并写下

#!/bin/bash
export MY_DATA=42

退出保存,然后在终端中输入

 source ./test.sh

然后在终端中输入

上述过程解析

  • export关键字用于定义一个环境变量
  • source命令用于将脚本中的环境变量生效,生效后的作用就是让其他脚本可识别该变量
    • 因此,假如我们重新定义一个新的脚本,输入echo MY_DATA,是可以输出该值的
  • env命令用于列出所有的环境变量 

特殊变量

三种引号的作用与区别

  • 双引号:可以解析变量的值
  • 单引号:不能解析变量的值,直接将单引号中的内容作为字符串处理
  • 反引号(数字键1前的按键):引用系统命令
#!/bin/bash
num=42
echo "num=$num"
echo 'num=$num'#直接将$num作为字符串处理。并不会解析num的值

echo "date is `date`"

上述代码的运行结果如下所示

小括号与大括号

  • ():由子shell完成,不会影响当前shell的值
  • {}:由当前shell完成,通常用于作为变量引用的边界
#!/bin/bash
data=42
(
#以下内容由子shell完成,不会影响外边data的值
data=43
echo "内部data值为:$data"
)

echo "外部data值为:$data"
#使用{}将data变量的引用与外部的eee三个字符区分开
echo "${data}eee"
echo ">>>>>>>"
echo "$dataeee"

运行结果

因此,一个好的习惯应当是,在引用变量的时候,使用{}将其包裹 

参数传递

位置参数传递

shell中用$1、$2、$3来传递外部的第一个参数、第二个参数、第三个参数等等,该参数传递方式称为位置参数传递

创建一个test.sh脚本,内容定义如下

#!/bin/bash
echo "第一个参数值:$1"
echo "第二个参数值:$2"
echo "第三个参数值:$3"

 保存退出,在命令行中执行脚本,并传递参数

./test.sh 42 43 45

运行结果为

选项参数传递

如果想实现选项参数传递,而不依赖于位置,可参考

shell脚本实现长短项参数设置_shell脚本处理长参数-****博客

获取参数相关信息

  • $#:获取传入的参数个数
  • $@:获取所有的参数内容,其中每个参数都会作为独立的字符串处理,假设输入参数是 one two three,使用 "$@" 会得到 "one""two""three" 三个独立的参数。
  • $*:获取所有的参数内容,并将所有参数作为一个整体处理。输入参数 one two three,使用 "$*" 会得到 "one two three",成为一个单一字符串。
#!/bin/bash
echo "第一个参数值:$1"
echo "第二个参数值:$2"
echo "第三个参数值:$3"
echo "the number of all parms is: $#"
echo "all parms value is: $@"
echo "all parms value is: $*"

for parm in "$@"; do
    echo "${parm}"
done

for parm in "$*"; do
    echo "${parm}"
done

运行结果

 其余预设变量

  • $?:获取命令执行后返回的状态,0表示执行成功,无错误,非0表示执行失败,有错误
  • $0:获取当前执行的进程名
  • $$:获取当前执行的进程号

 代码实例

#!/bin/bash
function func1(){
#返回非0状态,表示func1函数执行出错
    return 1
}

function func2(){
#获取传递给func2的参数
    parm1=$1
    parm2=$2
    echo "parm1 is ${parm} and the parm2 is ${pamr2}"

#返回0,表示func2函数执行无误
    return_value="yes"
    echo ${return_value}
    return 0
}

func1
echo "func1 return status is $?"

func2 42 43
echo "func2 return status is $?"

return_value=$(func2 54 56)
echo "func2 return status is $? ,and the return value is $return_value"

上述代码解析:

  • function关键字用于定义一个函数
  • shell中的return关键字是返回函数执行状态的,return后的值只能是数字,不能是其余字符串信息
  • 如果想返回函数体内的值给函数外部执行者,使用echo命令
  • shell中函数参数的传递,同样也使用上述的位置参数传递

执行结果

获取进程名与进程号

#!/bin/bash
echo "process name is $0"
echo "process number is $$"

字符串处理

#!/bin/bash
str="hello hello world"

#获取
echo "字符串长度:${#str}"

#从下标为3的字符开始截取子串
echo "${str:3}"

#从下标为3的字符开始截取长度为4的子串
echo "${str:3:4}"

#将字符串中的第一个hello替换为hahaha
new_str="${str/hello/hahaha}"
echo "$new_str"

#将字符串中的所有hello替换为hhhhh
new_str1="${str//hello/hhhhh}"
echo "$new_str1"

条件测试

条件测试使用[ condition ]判断condition是否为真

使用方括号时,要注意在条件两边加上空格,同时,运算符和操作数之间必须有空格。缺少空格会导致语法错误。

文件测试

判断文件状态

  • -e:判断文件是否存在
  • -d:判断文件是否是一个目录
  • -f:判断文件是否是一个文件
  • -s:判断文件是否非空
  • -r:判断文件是否可读
  • -w:判断文件是否可写
  • -x:判断文件是否可执行
  • -L:判断该文件是否是符号链接
  • -c:判断是否是字符设备
  • -b:判断是否是块设备
#!/bin/bash

for item in `ls`; do
    if [ -d "$item" ]; then
        echo "$item 是一个目录"
    elif [ -f "$item" ]; then
        echo "$item 是一个普通文件"
    else
        echo "$item 是其他类型"
    fi
done

 

字符串测试

  • =:判断两个字符串是否相等
  • !=:判断两个字符串是否不相等
  • -z:判断是否是空串
  • -n:判断是否是非空串
#!/bin/bash

read -p "str1=" str1
read -p "str2=" str2

#如果str1和str2都不为空
if [[ ! -z ${str1} && ! -z ${str2} ]];then
    echo "$str1"
    echo "$str2"
#如果str1和str2的值相等
    if [ "$str1" = "$str2" ]; then
        echo "str1 equal str2"
    else
        echo "str1 not equal str2"
    fi
fi

 

数值测试

#!/bin/bash

read -p "num1=" num1
read -p "num2=" num2

if [ $num1 -eq $num2 ]; then
    echo "$num1 equal $num2"
elif [ $num1 -gt $num2 ];then
    echo "$num1 greater than $num2"
else
    echo "$num1 less than $num2 "
fi

 

控制语句

逻辑语句

  • 与运算:&&
  • 或运算:||
  • 非运算:!

条件语句

if语句

使用格式如下:

if [条件1]; then
    执行第一段程序
elif [条件2];then
执行第二段程序
else
    执行第三段程序
fi

结合上述字符串测试与数值测试案例学习即可

case语句

#!/bin/bash

read -p "please input choice yes or no >>> " choice

case $choice in
    yes | y* | Y*)
        echo "yes"
        ;;
    no | n* | N*)
        echo "no"
        ;;
    *)
        echo "others"
        ;;
esac

循环语句

for循环

#!/bin/bash

read -p "please input n is >>> " n
declare -i sum=0
declare -i i=0
for ((i=0;i<n;i++))
do
    sum=$sum+$i
done

echo "sum=$sum"

for item in `ls`; do
    if [ -d "$item" ]; then
        echo "$item 是一个目录"
    elif [ -f "$item" ]; then
        echo "$item 是一个普通文件"
    else
        echo "$item 是其他类型"
    fi
done

while循环

#!/bin/bash

read -p "请输入一个正整数: " n

while [ $n -gt 0 ]
do
    echo "当前数字是: $n"
    n=$((n - 1))
done

echo "循环结束!"

 

函数

函数定义

function 函数名(){
    函数体
}

函数的调用与返回

函数的调用和平时调用命令一样

写一个test.sh脚本,并定义文件内容如下: 

#!/bin/bash
function max(){
    if [ $1 -gt $2 ];then
        echo $1
    else
        echo $2
    fi
}

max_val=$(max $@)
echo "max num is $max_val"

然后在终端命令行输入

./test.sh 12 45

 执行结果如下所示

文件导入

定义一个max.sh文件

#!/bin/bash
function Max(){
    if [ $1 -gt $2 ];then
        echo $1
    else
        echo $2
    fi
}

然后再定义一个main.sh文件

#!/bin/bash
#导入max.sh文件
source max.sh

read -p "num1=" num1
read -p "num2=" num2
#使用max.sh文件中的Max函数
max_val=$(Max $num1 $num2)
echo "max_val is $max_val"

终端命令行执行

参考

shell脚本语言(超全超详细) - 知乎