Shell 脚本

一、走进 Shell 编程的大门

1)为什么要学 Shell?

学习 Shell 是为了提高我们自己工作效率,提高产出,让我们在更少的时间完成更多的事情。

一般 Shell 编程属于运维方面的知识,但我们做后端开发也是需要掌握的,对于 Shell 编程掌握程度的要求要比运维低。

目前 Linux 系统下最流行的运维自动化语言就是 Shell 和 Python 了。

两者区别

  • Shell 几乎是 IT 企业必须使用的运维自动化编程语言,特别是在运维工作中的服务监控、业务快速部署、服务启动停止、数据备份及处理、日志分析等环节里,shell 是不可缺的。
  • Python 更适合处理复杂的业务逻辑,以及开发复杂的运维软件工具,实现通过 web 访问等。

Shell 是一个命令解释器,解释执行用户所输入的命令和程序。一输入命令,就立即回应的交互的对话方式。

2)什么是 Shell?

Shell 编程就是对一堆 Linux 命令的逻辑化处理。

3)第一个 Shell 脚本

1.新建一个文件 helloworld.sh:touch helloworld.sh,扩展名为 sh(sh 代表 Shell)
2.使脚本具有执行权限:chmod +x helloworld.sh
3.使用 vim 命令修改 helloworld.sh 文件:vim helloworld.sh,内容如下 ↓

#!/bin/bash
echo  "helloworld!!!"

shell 的第一行比较特殊,一般都会以 #! 开始来指定使用的 shell 类型。在 linux 中,除了 bash shell 以外,还有很多版本的 shell, 例如 zsh、dash 等等...不过 bash shell 还是我们使用最多的

4.执行脚本:./helloworld.sh

注意,一定要写成 ./helloworld.sh ,而不是 helloworld.sh ,运行其它二进制的程序也一样,直接写 helloworld.sh ,linux 系统会去 PATH 里寻找有没有叫 helloworld.sh 的,而只有 /bin, /sbin, /usr/bin,/usr/sbin 等在 PATH 里,你的当前目录通常不在 PATH 里,所以写成 helloworld.sh 是会找不到命令的,要用 ./helloworld.sh 告诉系统说,就在当前目录找。

image

二、Shell 变量

1)Shell 变量介绍

Shell 编程中一般分为三种变量

  1. 自定义变量: 仅在当前 Shell 实例中有效,其他 Shell 启动的程序不能访问局部变量。
  2. 环境变量:系统中已定义的环境变量,这类变量可以直接使用;env 命令可以查看所有环境变量,set 命令查看所有环境变量与自定义变量
  3. Shell 变量:Shell 变量是由 Shell 程序设置的特殊变量。Shell 变量中有一部分是环境变量,有一部分是局部变量,这些变量保证了 Shell 的正常运行

常用的环境变量

PATH:决定了 shell 将到哪些目录中寻找命令或程序
HOME:当前用户主目录
HISTSIZE:历史记录数
LOGNAME:当前用户的登录名
HOSTNAME:指主机的名称
SHELL:当前用户 Shell 类型
LANGUAGE:语言相关的环境变量,多语言可以修改此环境变量
MAIL:当前用户的邮件存放目录
PS1:基本提示符,对于 root 用户是#,对于普通用户是$

例:

#!/bin/bash
#自定义变量
hello="hello world"
echo $hello
echo  "helloworld!"
#环境变量
echo $HOME

image

变量名命名规则

  • 命名只能使用英文字母,数字和下划线,首个字符不能以数字开头
  • 中间不能有空格,可以使用下划线 _
  • 不能使用标点符号
  • 不能使用bash里的关键字(可用help命令查看保留关键字)

2)Shell 字符串

Shell 中的字符串可以用单引号,也可以用双引号。这点和 Java 中有所不同。

区别

  • 单引号:所有的特殊符号,如 $ 和反引号都没有特殊含义。
  • 双引号:除了 "$","" 和反引号,其他的字符没有特殊含义。

单引号字符串:

#!/bin/bash
type_1='Single'
str1='This is $type_1 quotation marks!'
echo $str1

输出:This is $type_1 quotation marks!

双引号字符串:

#!/bin/bash
type_2="Double"
str2="This is $type_2 quotation marks!"
echo $str2

输出:This is Double quotation marks!

拼接字符串:

#!/bin/bash
joint="joint"
# 使用双引号拼接
joint1="Concatenation string,"$joint"!"
echo $joint1
joint2="Concatenation string,${joint}!"
echo $joint2
# 使用单引号拼接
joint3='Concatenation string,'$joint'!'
echo $joint3
joint4='Concatenation string,${joint}!' #单引号内所有特殊符号都无意义
echo $joint4

输出:
Concatenation string,joint!
Concatenation string,joint!
Concatenation string,joint!
Concatenation string,${joint}!

获取字符串长度:

#!/bin/bash
str="1234567"
echo ${#str}

输出:7

截取字符串:

#!/bin/bash
zimu="abcdefghijklmnopqrstuvwxyz"
echo ${zimu:0:10} # startIdx 包含、endIdx 不包含

输出:abcdefghij

表达式截取字符串

  • %:表示删除从后匹配, 最短结果
  • %%:表示删除从后匹配, 最长匹配结果
  • #:表示删除从头匹配, 最短结果
  • ##:表示删除从头匹配, 最长匹配结果
  • 注: *为通配符, 意为匹配任意数量的任意字符
#!/bin/bash
var="https://www.runoob.com/linux/linux-shell-variable.html"
s1=${var%%t*}
echo $s1
s2=${var%t*}
echo $s2
s3=${var%%.*}
echo $s3
s4=${var#*/}
echo $s4
s5=${var##*/}
echo $s5

输出:h
https://www.runoob.com/linux/linux-shell-variable.h
https://www
/www.runoob.com/linux/linux-shell-variable.html
linux-shell-variable.html

3)Shell 数组

bash 支持一维数组(不支持多维数组),并且没有限定数组的大小。

下面演示创建数组、获取数组长度、获取/删除特定位置的数组元素、删除整个数组以及遍历数组。

#!/bin/bash
#创建数组,多个元素使用空格分开
array=(1 2 3 4 5);
for obj in ${array[@]};
do 
  echo $obj;
done
#获取数组长度
length1=${#array[@]}
length2=${#array[*]}
echo "--------------"
#输出数组长度
echo "length1="$length1
echo "length2="$length2
echo "--------------"
#获取指定下标元素
echo "array[2]="${array[2]}
echo "--------------"
#删除指定下标元素
unset array[1]
for i in ${array[@]};
do 
  echo $i ;
done
echo "--------------"
#删除数组中的所有元素
unset array; 
for j in ${array[@]};
do 
  echo $j ;
done
echo "--------------"

image

三、Shell 运算符

shell 支持多种运算符:

  • 算数运算符
  • 关系运算符
  • 布尔运算符
  • 字符串运算符
  • 文件测试运算符

表达式和运算符之间要有空格,例如 1+1 是不对的,必须写成 1 + 1

完整的表达式要被反引号 `` 包含(不是单引号)

1)算术运算符

image
例:

#!/bin/bash
a=3;b=3;
result=`expr $a + $b`
echo "$a + $b = $result"

输出:3 + 3 = 6

2)关系运算符

image

例:

#!/bin/bash
score=90;
maxscore=100;
if [ $score -eq $maxscore ]
then
   echo "A"
else
   echo "B"
fi

输出:B

3)逻辑运算符

image

例:

#!/bin/bash
flag=$(( 1 && 0))
echo $flag;

输出:0

4)布尔运算符

image

例:

#!/bin/bash
a1=10
a2=20
if [ $a1 != $a2 ]
then
  echo "A"
else
  echo "B"
fi

输出:A

5)字符串运算符

image

例:

#!/bin/bash
a3="abc";
b3="efg";
if [ $a3 = $b3 ]
then
   echo "a3 等于 b3"
else
   echo "a3 不等于 b3"
fi

输出:a3 不等于 b3

6)文件相关运算符

image

例:

#!/bin/bash
file="/var/tmp/20230501.txt"
if [ -r $file ]
then
   echo "文件可读"
else
   echo "文件不可读"
fi
if [ -d $file ]
then
   echo "文件是个目录"
else
   echo "文件不是个目录"
fi
if [ -e $file ]
then
   echo "文件存在"
else
   echo "文件不存在"
fi

输出:
文件可读
文件不是个目录
文件存在

四、Shell 流程控制

1)if条件语句

与 Java、PHP 等语言不一样,sh 的流程控制不能包含空语句也就是什么都不做的语句。

if(true){
  System.out.println("Hello");
}else{
  // 不做任何事情,这里是允许的
}

例:

#!/bin/bash
a1=2; b1=7;
if [ $a1 -eq $b1 ]
then
  echo "a1 等于 b1"
elif [ $a1 -gt $b1 ]
then
  echo "a1 大于 b1"
else
  # echo "b1 小于 b1" # 注释后会出错,不允许什么也不做的语句
fi

输出:b1 小于 b1

2)for 循环语句

与其他编程语言类似,Shell支持for循环。

例:输出列表中的数据

#!/bin/bash
for val in 1 2 3 4 5
do
    echo "The val is: $val"
done

输出:
The value is: 1
The val is: 2
The val is: 3
The val is: 4
The val is: 5

例:产生 10 个随机数

#!/bin/bash
for i in {0..9};
do
  echo "random.val="$RANDOM;
done

输出:
random.val=5070
random.val=14653
random.val=31878
random.val=26394
random.val=9457
random.val=1887
random.val=5887
random.val=4853
random.val=9231
random.val=15433

例:输出 1 - 5

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

输出:
out 1
out 2
out 3
out 4
out 5

3)while 语句

while 语法格式为:

while condition
do
    command
done

例:

#!/bin/bash
idx=1
while(( $idx<=5 ))
do
    echo "while print > "$idx
    let "idx++" # Bash let 命令,变量计算中不需要加上 $ 来表示变量
done

输出:
while print > 1
while print > 2
while print > 3
while print > 4
while print > 5

五、Shell 函数

linux shell 可以用户定义函数,然后在shell脚本中可以随便调用。

函数格式:

[ function ] funname [()]
{
    action;
    [return int;]
}

1)无参数无返回值

#!/bin/bash
hello(){
  echo "this is my function"
}
echo "fun start"
hello
echo "fun end"

输出:
fun start
this is my function
fun end

2)无参数有返回值

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

注意:所有函数在使用前必须定义。这意味着必须将函数放在脚本开始部分,直至 shell 解释器首次发现它时,才可以使用。调用函数仅使用其函数名即可。

#!/bin/bash
funWithReturn(){
    echo -n "输入第一个数字: "
    read  a
    echo -n "输入第二个数字: "
    read  b
    echo "两个数字分别为 $a$b !"
    return $(($a+$b))
}
funWithReturn
echo "输入的两个数字之和为 $?"

输出:
输入第一个数字: 33
输入第二个数字: 7
两个数字分别为 33 和 7 !
输入的两个数字之和为 40

3)带参数的函数

#!/bin/bash
funWithParam(){
    echo "Expression \$1 value = $1"
    echo "Expression \$2 value = $2"
    echo "Expression \$10 value = $10"
    echo "Expression \${10} value = ${10}"
    echo "Expression \$11 value = $11"
    echo "Expression \${11} value = ${11}"
    echo "Params size =  $#"
    echo "Out all params > $*"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73

输出:
Expression $1 value = 1
Expression $2 value = 2
Expression $10 value = 10
Expression ${10} value = 34
Expression $11 value = 11
Expression ${11} value = 73
Params size = 11
Out all params > 1 2 3 4 5 6 7 8 9 34 73

posted @   ohmok  阅读(78)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示

目录导航