shell脚本基础详细学习(更新中)
shell简单介绍
Shell不仅仅是充当用户与UNIX或者localhost交互的角色,还可以作为一种程序设计
语言来使用。通过Shell编程,可以实现许多非常实用的功能,提高系统管理的自动化水平。
如果有一系列经常需要使用的命令,把它存储在一个文件里,shell可以读取这个文件
并顺序执行其中的命令,我们把这样的文件就叫shell脚本。shell脚本按行解释文件里的命令。
shell脚本的基本元素
对于一个基本的Shell程序来说,应该拥有以下基本元素:
1.声明:声明用哪个命令解释器来解释并执行当前脚本文件中的语句,一般写的解释器为
#!/bin/bash 。
2.命令:可执行语句,实现程序的功能。
3.注释:说明某些代码的功能,通过在代码中增加注释可以提高程序的可读性。
注释
1. 单行注释(#)
在 shell 脚本中,#
符号用于添加单行注释。从 #
开始,一直到这一行的末尾,所有内容都会被解释器忽略。其语法格式为:
# 这是一个单行注释
echo "Hello World" # 这是行尾注释
2. 多行注释(: '...')
若要添加多行注释,可使用 : '注释内容'
这种形式。需要注意的是,这种注释方式不能嵌套使用。示例如下:
: '
这是一个多行注释
可以包含多行文本
'
echo "Hello World"
另外,还有一种利用未使用变量的替代方法:
if false; then
echo "第一行注释"
echo "第二行注释"
fi
单行注释是最常用的注释方式,而多行注释则适用于需要添加大块说明文字的场景。
3. 多行注释(:配合here document使用)
这是使用 Here Document( heredoc )创建注释块的方式,在 Shell 脚本中非常常见。以下是详细说明:
简单示例
:<<BLOCK
这是一个多行注释
可以包含任意文本,甚至包含 shell 命令、变量等
但不会被执行
BLOCK
:
:是 Shell 内置命令,相当于 "空操作"(null command),不执行任何操作,仅返回状态码 0。<<BLOCK
:Here Document 标记,表示后续内容直到BLOCK
结束都作为输入传递给:
命令。BLOCK
:自定义的结束标记(可以使用任何合法标识符,如EOF
、COMMENT
等)。
关键点:
-
注释块可以包含任意内容:
:<<COMMENT 这是有效的注释 $变量不会被解析 $(命令) 也不会被执行 even if [ $x -eq 1 ]; then echo "not executed"; fi COMMENT
-
结束标记必须单独一行:
:<<EOF 正确:EOF 在单独一行 EOF:<<END 错误:END 后面有空格或其他字符 END
-
标记名称建议大写:避免与变量名冲突(如
end
可能是已定义的变量)。
shell脚本编写规范
# Date:创建日期
# Author:作者
# Mail:联系方式
# Function:功能
# Version:版本
[root@kittod ~]# echo hehe
hehe
[root@kittod ~]# echo haha
haha
[root@kittod ~]# echo "Welcome to bash"
Welcome to bash
[root@kittod ~]# echo 'Welcome to bash'
Welcome to bash
2、上面的方法看起来效果一样,但是在某些场合会得到不一样的结果
[root@free ~]# echo 'the current directory is `pwd`' 单引号
the current directory is `pwd`
[root@free ~]# echo "the current directory is `pwd`" 双引号
the current directory is /root
[root@free ~]# echo "directory is `pwd`"
directory is /root
[root@free ~]# echo "`pwd`"
/root详细解释``作用
1. 命令替换的作用
借助命令替换,能够把命令的输出结果当作参数,嵌入到其他命令之中。就像这样:
echo "当前目录是 `pwd`" # 先执行 pwd 命令,再把结果(如 /root)嵌入到字符串里
输出结果为:
当前目录是 /root2. 反引号(`)与美元符号加括号($(...))的对比
命令替换有两种表示方式:
传统写法:使用反引号(`命令`)
现代写法:使用 $(命令)
下面是这两种写法的对比示例:
echo "`date`" # 输出当前日期时间(传统写法)
echo "$(date)" # 输出当前日期时间(现代写法)
现代写法更加方便简洁,嵌套更加方便,反引号在命令替换中要使用其本身要用转义字符。反引号(`)的核心作用是**执行命令并获取结果**,进而实现动态参数的生成或者信息的嵌入。不过,在新的脚本中,更推荐使用 $(...) 这种写法,因为它更加清晰,还支持嵌套功能。[root@kittod ~]# echo "hehe;hehe"
hehe;hehe
[root@kittod ~]# echo hehe;hehe
hehe
-bash: hehe: command not found

简单示例:
[root@kittod ~]# echo -n i have a cat
i have a cat[root@kittod ~]#
[root@kittod ~]# echo -e i\thave\ta\tcat
ithavetatcat
[root@kittod ~]# echo -e "i\thave\ta\tcat"
i have a cat
[root@kittod ~]# echo "1 2 3"
1 2 3
[root@kittod ~]# echo -e "1\t2\t3"
1 2 3
[root@kittod ~]# echo -e "1 2 3"
1 2 3
#设置字体颜色
[root@kittod ~]# echo -e "\e[1;31m This is red test \e[0m"
This is red test
\e[1;31m 将颜色设置为红色, \e[0m 将颜色重置,使用时只需要更换颜色代码即可
颜色代码
重置 0
黑色 30
红色 31
绿色 32
黄色 33
蓝色 34
洋红 35
青色 36
白色 37
#设置背景颜色[root@kittod ~]# echo -e "\e[1;42m This is red test bg \e[0m"
This is red test bg
颜色代码
重置 0
黑色 40
红色 41
绿色 42
黄色 43
蓝色 44
洋红 45
青色 46
白色 47
连续反斜杠加-e和默认的区别
1. 不带 -e 参数的 echo
bash
echo today is\\\\\\ sunday
# 输出:today is\\\ sunday
规则:默认情况下,echo 会将连续的反斜杠按奇数 / 偶数处理:
偶数个反斜杠(如 \\、\\\\):每两个反斜杠合并为一个(\\ → \)。
奇数个反斜杠(如 \、\\\):最后一个反斜杠会转义其后的字符(若后无字符则保留)。
步骤解析:
bash
# 原始输入:today is\\\\\\ sunday
# 处理反斜杠:
# 1. \\\\ → \\(前四个反斜杠合并为两个)
# 2. \\ → \(最后两个反斜杠合并为一个)
# 最终输出:today is\\\ sunday2. 带 -e 参数的 echo
bash
echo -e today is\\\\\\ sunday
# 输出:today is\\ sunday
规则:-e 参数启用反斜杠转义功能,但 echo 会先按原始规则处理反斜杠,再应用转义:
偶数个反斜杠:合并后,若剩余偶数个,则继续两两合并;若剩余奇数个,则最后一个用于转义。
特殊转义符(如 \n、\t):会被解释为对应功能。
步骤解析:
bash
# 原始输入:today is\\\\\\ sunday
# 1. 原始反斜杠处理:
# \\\\ → \\(前四个反斜杠合并为两个)
# \\ → \(最后两个反斜杠合并为一个)
# 中间步骤:today is\\\ sunday# 2. 应用 -e 参数的转义:
# \\\ → \\(前两个反斜杠合并为一个,最后一个转义空格失败,保留)
# 最终输出:today is\\ sunday3. 关键区别
参数 反斜杠处理逻辑 示例(输入 \\\\\\) 输出结果
无 -e 奇偶合并,奇数保留最后一个 \\\\\\ → \\\ \\\
-e 先奇偶合并,再转义特殊字符 \\\\\\ → \\\ → \\ \\
4. 常见误区
误解一:认为 -e 会直接解析原始反斜杠。
实际上,echo 会先处理反斜杠(合并 / 转义),再应用 -e 的特殊转义规则。
误解二:连续反斜杠在 -e 下总是成对解析。
只有合并后的奇数个反斜杠中的最后一个才会触发转义,例如:
bash
echo -e '\\\\\n' # 输出:\\(前四个合并为两个,最后一个转义 \n)5. 如何正确输出多个反斜杠?
输出偶数个反斜杠:直接使用两倍数量的反斜杠。
bash
echo '\\\\' # 输出:\\(默认模式)
echo -e '\\\\' # 输出:\\(-e 模式)输出奇数个反斜杠:在 -e 模式下,需要额外的反斜杠来转义。
bash
echo -e '\\\\\\' # 输出:\\\(前四个合并为两个,最后一个保留)总结
默认 echo:按奇偶合并反斜杠,奇数个保留最后一个。
echo -e:先处理反斜杠,再转义特殊字符(如 \n、\t)。
建议:若需精确控制反斜杠数量,优先使用单引号 ' 包裹字符串,并结合 -e 参数。
文本颜色样式设置代码详解
命令解析
echo -e "\e[1;31m This is red text \e[0m"
echo -e:启用对反斜杠转义字符的解释(如\e、\n等)
\e[1;31m:ANSI 转义序列,用于设置文本样式
\e:转义字符(ASCII 27,也可写作\033或\x1B)
[:控制序列引入符(CSI)
1:设置文本为粗体(可选参数)
31:设置文本颜色为红色(31 代表红色,32 为绿色,33 为黄色,依此类推)
m:设置属性命令
This is red text:实际显示的文本内容
\e[0m:重置所有文本属性,恢复默认样式
输出效果
当你运行这个命令时,终端会显示:
This is red text(实际显示为红色粗体)
然后恢复为默认文本样式。
其他颜色和样式选项
你可以通过修改转义序列中的数字来改变颜色和样式:
# 基本颜色代码
30: 黑色 31: 红色 32: 绿色 33: 黄色
34: 蓝色 35: 紫色 36: 青色 37: 白色# 背景颜色代码(40-47)
40: 黑底 41: 红底 42: 绿底 43: 黄底
44: 蓝底 45: 紫底 46: 青底 47: 白底# 样式代码
0: 重置 1: 粗体 4: 下划线 5: 闪烁 7: 反显
export命令详细解释
一、基本概念
环境变量 是 Shell 中存储的全局变量,可被当前 Shell 和所有子进程访问。而 局部变量 仅在当前 Shell 会话中有效,子进程无法继承。
export
的作用是:
- 将当前 Shell 中的局部变量转换为环境变量。
- 在定义变量时直接声明其为环境变量。
二、语法格式
export [变量名]=[值] # 定义并导出新变量
export [变量名] # 将已存在的局部变量导出为环境变量
export -f [函数名] # 导出函数,使其在子Shell中可用
export -n [变量名] # 取消变量的导出状态(使其变为局部变量)
export -p # 显示所有已导出的环境变量
三、核心用法
bash -c
会创建一个全新的子 shell 进程来执行命令,该子 shell 与当前 shell 相互隔离。用于测试很方便。
1. 定义并导出变量
export NAME="Doubao" # 定义并导出变量
echo $NAME # 输出: Doubao# 在子Shell中验证
bash -c 'echo $NAME' # 输出: Doubao(子Shell继承了环境变量)
2. 导出已存在的局部变量
AGE=25 # 定义局部变量
export AGE # 将局部变量导出为环境变量bash -c 'echo $AGE' # 输出: 25
3. 导出函数
greet() { echo "Hello $1"; }
export -f greet # 导出函数bash -c 'greet World' # 输出: Hello World(子Shell可调用该函数)
4. 取消导出状态
export LANG=en_US.UTF-8
export -n LANG # 取消LANG的导出状态
bash -c 'echo $LANG' # 输出为空(子Shell无法访问)
四、与变量作用域的关系
变量类型 | 定义方式 | 作用域 | 示例 |
---|---|---|---|
局部变量 | NAME=value | 仅当前 Shell | NAME=Doubao; echo $NAME |
环境变量 | export NAME=value | 当前 Shell 及所有子进程 | export NAME=Doubao; bash -c 'echo $NAME' |
全局变量 | 在.bashrc 等文件中定义 | 所有新启动的 Shell | 在.bashrc 中添加:export PATH="$PATH:/new/dir" |
五、常见应用场景
1. 设置 PATH 路径
export PATH="$PATH:/home/user/bin" # 添加自定义目录到PATH
2. 配置语言环境
export LANG=en_US.UTF-8 # 设置语言编码
3. 在脚本中使用环境变量
# script.sh
#!/bin/bash
echo "Hello $USER, today is $(date +%A)"# 执行脚本(继承当前环境变量)
export USER="Doubao"
./script.sh # 输出: Hello Doubao, today is Friday
4. 临时测试环境变量
FOO=bar ./command # 仅在执行command时设置FOO,执行后失效
六、注意事项
-
仅对当前 Shell 及子进程有效
export
设置的变量只在当前 Shell 会话和其启动的子进程中生效。关闭终端后,设置会丢失。 -
永久生效需配置文件
若要每次登录都生效,需将export
命令添加到 Shell 配置文件中,如:# 对所有用户生效 /etc/profile# 对当前用户生效 ~/.bashrc 或 ~/.bash_profile
-
子 Shell 修改不影响父 Shell
子进程中修改环境变量不会影响父进程:bash -c 'export TEST=123' # 子Shell设置TEST echo $TEST # 父Shell中TEST仍为空
七、与其他命令的对比
命令 | 作用 | 示例 |
---|---|---|
export | 设置环境变量,使其在子进程中可用 | export VAR=value |
declare | 声明变量类型(如整型、数组等) | declare -i NUM=100 |
readonly | 设置只读变量,不可修改或取消 | readonly PATH |
set | 显示或设置 Shell 选项和变量 | set -x (开启调试模式) |
总结
export
是 Shell 编程中用于管理环境变量的核心工具,通过它可以灵活控制变量的作用域,确保配置在不同进程间传递。合理使用 export
能帮助你更好地管理系统环境和编写可复用的脚本。
read命令详解
在 Bash 中,read
命令用于从标准输入(通常是键盘)读取用户输入,并将其赋值给一个或多个变量。它是交互式脚本、配置读取和数据处理的重要工具。以下是对 read
命令的详细解析:
基本语法
read [选项] [变量名1 变量名2 ...]
- 功能:读取一行输入,按空格分割后赋值给对应变量。若变量数少于输入字段数,最后一个变量会包含剩余所有字段。
- 示例:
read name age # 输入 "Alice 25" echo "Name: $name, Age: $age" # 输出: Name: Alice, Age: 25
常用选项
选项 | 功能描述 |
---|---|
-p "提示信息" | 显示提示信息,无需额外使用 echo 。 |
-t 超时秒数 | 设置超时时间,超时后返回非零状态(需结合 -n 或 -s 使用)。 |
-s | 静默模式,不显示输入内容(适用于密码输入)。 |
-n 字符数 | 读取指定数量的字符后立即返回,无需按回车。 |
-r | 禁用反斜杠 \ 的转义功能(原始输入)。 |
-d 分隔符 | 使用指定字符作为输入结束标记(默认是换行符 \n )。 |
选项示例
-
带提示信息的输入:
read -p "请输入用户名: " username echo "欢迎, $username!"
-
密码输入(静默模式):
read -s -p "请输入密码: " password echo # 手动换行 echo "密码已输入"
-
限时输入:
if read -t 5 -p "5秒内按Y确认: " answer; thenecho "你输入了: $answer" elseecho "超时!" fi
-
读取单个字符:
read -n 1 -p "按任意键继续..." echo # 手动换行
-
原始输入(保留反斜杠):
read -r path # 输入 "C:\Users\Alice" echo "$path" # 输出: C:\Users\Alice(而非 C:UsersAlice)
高级用法
-
从文件读取:
while read -r line; doecho "读取行: $line" done < filename.txt # 逐行读取文件内容
-
读取特定分隔符的输入:
read -d '/' var1 var2 # 输入 "apple/banana" echo "Var1: $var1, Var2: $var2" # 输出: Var1: apple, Var2: banana
-
读取数组:
read -a fruits # 输入 "apple banana cherry" echo "第二个水果: ${fruits[1]}" # 输出: banana
返回状态与错误处理
- 成功:读取到有效输入时返回状态码
0
。 - 失败:
- 超时(
-t
选项)返回非零状态。 - 读取到文件结束符(EOF,如按
Ctrl+D
)返回非零状态。
- 超时(
示例:检查超时
if read -t 3 -p "快速回答: " answer; thenecho "回答: $answer"
elseecho "超时!" >&2exit 1
fi
注意事项
-
输入分割规则:
read
默认使用IFS
(内部字段分隔符,默认为空格、制表符、换行符)分割输入。如需自定义分割符,可临时修改IFS
:IFS=',' read -r a b c <<< "1,2,3" echo "a=$a, b=$b, c=$c" # 输出: a=1, b=2, c=3
-
空变量处理:若用户直接按回车,变量会被赋值为空字符串。可通过
read -e
启用 readline 编辑功能,提供默认值:read -e -p "请输入文件名 [default.txt]: " file file=${file:-default.txt} # 使用默认值
总结
read
命令是 Bash 中处理用户输入的核心工具,通过灵活搭配选项(如 -p
、-s
、-t
),可以实现从简单提示到复杂交互式脚本的各种需求。熟练掌握 read
能显著提升脚本的用户体验和功能完整性。