1. 什么是shell
Shell,翻译成中文就是 "壳",它是 操作系统的外壳,用来包裹和操作 内核(Kernel) 的工具。简单来说,Shell 就是用户和操作系统之间的沟通桥梁,让用户可以通过命令来让系统干活。

shell也是一门功能强大的编程语言,具有 易编写、易调试、灵活性强 的特点,尤其适合系统管理、批量任务处理、自动化运维。shell脚本就是一种专门使用shell语言编写的脚本程序,以.sh结尾的文件。它虽然没有C++、Java、Python等一系列高级语言功能强大,但是在服务器运维领域以及嵌入式开发领域,shell脚本具有举足轻重的地位。
2. linux中常见的shell
linux有很多shell 的实现,通过命令cat /etc/shells可以查看linux中的shell。常见的有/bin/bash /bin/sh 等等......

在ubuntu中,默认的shell是/bin/bash,可以通过echo $SHELL查看

3. shell 脚本的执行方式
1 直接用解释器执行
bash hello.sh
sh hello.sh
特点:不需要给脚本加执行权限
可以用不同的shell解释器去执行
脚本第一行#!/bin/bash指定的解释器不会生效,取决于你用的哪个命令
ps:#!/bin/bash 是用来指定脚本的解释器,使用/bin/bash来执行。加上它的主要原因是为了确保脚本在执行时能够正确调佣指定的解释器,不同的系统可能有不同的默认shell,如果没有指定解释器,系统将会用默认的解释器来执行。
如果脚本使用了bash特有的语法或者功能,使用sh肯能导致脚本执行错误,加上后,脚本无论在哪台机器上运行,都会使用dash来执行,避免了因为默认shell不同而导致的问题。
2 赋予执行权限后直接运行
chmod +x hello.sh
./hello.sh
特点:需要有执行权限
4 shell语言
4.1 预定义变量与位置变量
预定义变量(有时也称为环境变量或内置变量)是在 Shell 环境中自动存在的变量,Shell 会在启动时定义这些变量,用户不需要显式声明它们。
位置变量是指在脚本或函数中,按位置传递的参数。它们的值是通过传递给脚本或函数的参数来确定的。
$0 :shell脚本的名字
$# :位置参数的个数
$? 上一个命令的执行状态或者获取shell函数的返回值
$$ 获取shell脚本的进程号
$1 - $9 第一个参数~第九个参数,空格作为分隔符
$* 获取所有位置的参数,每个参数是独立的字符串
$@ 获取所有位置的参数,但会将所有参数当作一个整体的字符串来处理
示例
#!/bin/bash
echo "脚本的名称$0"
echo "位置参数的个数$#"
echo "上一个命令的执行结果$?"
echo "进程号$$:"
echo "第1个位置的参数$1"
echo "第2个位置的参数$2"
echo "第3个位置的参数$3"
echo "第4个位置的参数$4"
echo "第5个位置的参数$5"
echo "第6个位置的参数$6"
echo "第7个位置的参数$7"
echo "第8个位置的参数$8"
echo "第9个位置的参数$9"
echo "所有位置的参数$*"
echo "所有位置的参数$@"

ps: $*和$@的区别
$@ 和 $* 都表示传递给脚本或函数的所有参数,但它们在处理参数时有所不同,尤其是在涉及到多个参数时。
$@:将每个参数视为独立的字符串。如果参数包含空格或其他分隔符,$@ 会将其作为单独的参数处理。
$\*:将所有的参数作为一个整体的单一字符串。多个参数会被一个分隔符(通常是空格)连接在一起。
示例:
echo "\$@ example:"
for arg in "$@"; do
echo "$arg"
done
echo "--------------------"
echo "\$* example:"
for arg in $*; do
echo "$arg"
done
#运行
./_01variable.sh "what is your name"
4.2 用户自定义变量
在 Shell 脚本中,用户可以自定义变量来存储值并进行操作。下面是如何定义和使用用户自定义变量的基本方法:
定义和赋值:
变量名和等号之间不能有空格
赋值给变量时,变量的值可以使字符串、数值或其他数据。变量没有类型,不需要定义,直接使⽤
语法: 变量名=值
引用变量:在变量前加上$符号
示例:
#!/bin/bash
name=lcc
age=18
echo "名字:$name"
echo "年龄:$age"

4.3 字符串操作
在 Shell 脚本 中,字符串操作非常常见。你可以使用多种方法来处理字符串,例如连接字符串、提取子字符串、查找字符串、字符串长度等。
4.3.1 字符串连接
可以简单地通过直接将两个字符串放在一起进行连接。
#!/bin/bash
str1="Hello"
str2="shell"
result="$str1 $str2"
echo "$result" # 输出 "Hello shell"
4.3.2 获取字符串长度
使用 ${#string} 获取字符串的长度。
#!/bin/bash
str="Hello World"
len=${#str}
echo "字符串长度: $len"
# 输出 "字符串长度: 11"
4.3.3 提取子字符串
可以通过 ${string:start:length} 来提取字符串中的子串。
-
start:起始位置(从0开始)
-
length:子字符串的长度(可选,如果省略则截取从 start 开始到字符串结束)
#!/bin/bash
str="Hello World"
substr=${str:0:5} # 提取从位置 0 开始的长度为 5 的子字符串
echo "$substr" # 输出 "Hello"
4.3.4 查找子字符串
使用 indexOf 可以查找某个子字符串在主字符串中的位置(如果存在)。在 Shell 中,通常使用 expr index 或者 [[ ]] 判断是否包含。
#!/bin/bash
str="Hello World"
if [[ "$str" == *"World"* ]]; then
echo "找到啦!"
else
echo "找不到喔!"
fi
4.3.5 替换字符串
可以使用 ${string//old/new} 来替换字符串中的内容。
在使用该表达式时,如果old前面是一个 / 则代表替换找到的第一个,如果是 // 则替换所有字符。在使用时,如果不写 new 则是删除掉字符 old 。
#!/bin/bash
str="Hello World"
new_str=${str/World/shell} # 替换第一个匹配到的 "World" 为 "shell"
echo "$new_str" # 输出 "Hello shell"
str="Helloooooo World"
new_str=${str//o/} # 删除所有的 "o"
echo "$new_str" # 输出 "Hell Wrld"
4.4 常用功能语句
4.4.1 echo
echo是最常用的输出命令,用于在终端打印文本。
-e 选项允许解释转义字符,例如 \n 代表换行。
-n:当没有的时候,echo输出结尾自动添加了换行,而使用-n后光标停留在同一行的末尾,没有换行。
4.4.2 printf
用于格式化输出,类似于 C 语言中的 printf 函数,它提供更多的控制格式功能。
pi=3.14159
printf "Pi is approximately %.2f\n" $pi
#%.2f 用于输出浮点数,保留两位小数
4.4.3 read
命令用于从用户输入获取数据
#!/bin/bash
echo "请输入姓名和年龄:"
read name age
echo "姓名:$name ,年龄:$age"

4.4.4 test 或 []
test 命令用于条件判断,通常用于 if 语句中
常用的测试选项:
-eq:相等
-ne:不等
-gt:大于
-lt:小于
-ge:大于等于
-le:小于等于
-z:判断字符串是否为空
-n:判断字符串是否非空
4.4.5 expr 或 (())
expr用于执行算术运算、字符串操作等。它在早期的 Shell 脚本中非常常见,但它有一些限制,比如它不能直接处理浮点数运算、运算符之间需要空格等。
(())用于进行算术运算,支持更简洁的语法。
a=10
b=5
result1=$(expr $a + $b)
((result2 = a + b))
echo "result1: $result1 result2: $result2"
4.5 流程控制
4.5.1 if语句
表达式为真,执⾏命令1和命令2,否则不执⾏。
if [ 表达式 ]
then
命令1
else
命令2
fi
#示例
#!/bin/bash
age=18
if [ $age -ge 18 ]; then #等同于test $age -ge 18
echo "成年啦"
else
echo "还未成年"
fi
4.5.2 case语句
case 语句用于根据多个不同条件来执行不同的代码块,它比多个 if 语句更简洁,适用于多选项的判断。
case $variable in
pattern1)
# 匹配 pattern1 执行的代码
;;
pattern2)
# 匹配 pattern2 执行的代码
;;
*)
# 如果都不匹配时执行的代码
;;
esac
#示例
#!/bin/bash
echo "输入一个数字:"
read num
case $num in
1)
echo "输入了1."
;;
2)
echo "输入了2."
;;
3)
echo "输入了3."
;;
*)
echo "无效数字."
;;
esac
4.5.3 for 循环
for variable in list; do
# 对每个元素执行的代码
done
#示例
#!/bin/bash
for i in 1 2 3 4 5; do
echo $i
done
4.5.4 while 循环
while 循环用于在指定条件为真时重复执行某些代码。
while [ condition ]; do
# 条件为真时执行的代码
done
#示例
#!/bin/bash
counter=1
while [ $counter -le 5 ]; do
echo $counter
((counter++)) # 自增
done
4.6 数组
在 Shell 脚本 中,数组(Array) 是一种非常重要的数据结构,可以用来存储多个元素(字符串或数字),通过索引访问。
#定义数组
array_name=(value1 value2 value3 ...)
#示例
name=(lcc zs ls)
#访问数组元素
# 在访问元素的时候和c语言的数组类似,通过下标进行访问,下标也是从0开始。
echo ${name[0]} #输出lcc
#获取数组长度
echo ${#name[@]} #输出:3
#数组增加元素
name+=(jj)
#修改元素
name[i]= new_value
#删除元素
unset name[i]
#删除整个数组
unset name
4.7 函数
函数作用
代码复用:避免重复代码,提高开发效率。
提高可读性:逻辑清晰,便于理解和修改。
方便调试和维护:将复杂任务拆分为多个小函数,易于排查错误。
参数化处理:通过传递参数,使代码更加通用和灵活。
增强脚本的可扩展性:可以在多个脚本中调用函数,提高扩展性。
#定义
函数名(){
函数体
}
#调用直接使用函数名即可
函数名
#示例
#!/bin/bash
sum_numbers() {
local sum=0
for num in "$@"; do #遍历所有传入的参数
sum=$(( sum + num )) #累加
done
echo $sum #输出计算结果
}
result=$(sum_numbers 1 2 3 4 5) #给函数传递参数直接写值即可,不用像c语言中需要写在括号中
echo "Sum: $result"
5 总结
Shell 语言的基础涵盖了变量定义与使用、字符串处理、输入输出以及各种流程控制和数据结构(如数组和函数)。这些基础知识使得我们能够编写出结构清晰、可维护、灵活的自动化脚本,适用于系统管理、任务自动化等多种场景。

3117

被折叠的 条评论
为什么被折叠?



