Bash 基础强化
深入掌握 Bash Shell 的核心特性,为编写高质量运维脚本打下坚实基础。
变量和数据类型
变量定义和使用
#!/bin/bash
# 变量赋值(等号两边不能有空格)
name="Linux"
version=5.15
count=100
# 变量引用
echo "System: $name"
echo "Version: ${version}"
# 只读变量
readonly PI=3.14159
# PI=3.14 # 报错:readonly variable
# 删除变量
unset count
特殊变量
#!/bin/bash
echo "脚本名称: $0"
echo "第一个参数: $1"
echo "第二个参数: $2"
echo "所有参数: $@"
echo "参数个数: $#"
echo "上一个命令退出状态: $?"
echo "当前进程 PID: $$"
echo "上一个后台进程 PID: $!"
数组操作
#!/bin/bash
# 定义数组
servers=("web1" "web2" "web3" "db1")
# 访问元素
echo "第一个服务器: ${servers[0]}"
echo "所有服务器: ${servers[@]}"
echo "数组长度: ${#servers[@]}"
# 遍历数组
for server in "${servers[@]}"; do
echo "处理服务器: $server"
done
# 关联数组(Bash 4.0+)
declare -A config
config[host]="192.168.1.10"
config[port]=22
config[user]="admin"
echo "SSH 连接: ${config[user]}@${config[host]}:${config[port]}"
字符串操作
字符串处理
#!/bin/bash
str="Hello, Linux World!"
# 字符串长度
echo "长度: ${#str}"
# 字符串截取
echo "截取: ${str:0:5}" # Hello
echo "从第7个字符开始: ${str:7}" # Linux World!
# 字符串替换
echo "${str/Linux/Unix}" # 替换第一个
echo "${str//o/O}" # 替换所有
# 删除子串
echo "${str#Hello, }" # 从开头删除最短匹配
echo "${str%World!}" # 从结尾删除最短匹配
# 大小写转换
upper="${str^^}" # 转大写
lower="${str,,}" # 转小写
echo "$upper"
echo "$lower"
字符串判断
#!/bin/bash
str="test.txt"
# 判断包含
if [[ $str == *".txt" ]]; then
echo "是文本文件"
fi
# 正则匹配
if [[ $str =~ ^test\..*$ ]]; then
echo "文件名以 test 开头"
fi
# 字符串比较
str1="abc"
str2="xyz"
if [[ $str1 < $str2 ]]; then
echo "$str1 在 $str2 之前"
fi
条件判断
文件测试
#!/bin/bash
file="/etc/passwd"
# 文件存在性
[ -e "$file" ] && echo "文件存在"
[ -f "$file" ] && echo "是普通文件"
[ -d "$file" ] && echo "是目录"
[ -L "$file" ] && echo "是符号链接"
# 文件权限
[ -r "$file" ] && echo "可读"
[ -w "$file" ] && echo "可写"
[ -x "$file" ] && echo "可执行"
# 文件比较
if [ file1 -nt file2 ]; then
echo "file1 比 file2 新"
fi
数值比较
#!/bin/bash
num1=10
num2=20
# 算术比较
if [ $num1 -eq $num2 ]; then echo "相等"; fi
if [ $num1 -ne $num2 ]; then echo "不等"; fi
if [ $num1 -lt $num2 ]; then echo "$num1 小于 $num2"; fi
if [ $num1 -gt $num2 ]; then echo "$num1 大于 $num2"; fi
if [ $num1 -le $num2 ]; then echo "$num1 小于等于 $num2"; fi
if [ $num1 -ge $num2 ]; then echo "$num1 大于等于 $num2"; fi
# 使用 (( )) 进行算术比较
if (( num1 < num2 )); then
echo "更简洁的比较方式"
fi
逻辑运算
#!/bin/bash
age=25
score=85
# AND 运算
if [ $age -ge 18 ] && [ $score -ge 60 ]; then
echo "成年且及格"
fi
# OR 运算
if [ $age -lt 18 ] || [ $score -lt 60 ]; then
echo "未成年或不及格"
fi
# NOT 运算
if [ ! -f "nofile.txt" ]; then
echo "文件不存在"
fi
# 使用 [[ ]] 的逻辑运算
if [[ $age -ge 18 && $score -ge 60 ]]; then
echo "推荐使用 [[ ]]"
fi
循环控制
for 循环
#!/bin/bash
# C 风格循环
for ((i=0; i<5; i++)); do
echo "计数: $i"
done
# 遍历列表
for item in apple banana orange; do
echo "水果: $item"
done
# 遍历文件
for file in /etc/*.conf; do
echo "配置文件: $file"
done
# 遍历命令输出
for user in $(cat /etc/passwd | cut -d: -f1); do
echo "用户: $user"
done
# 遍历数字序列
for num in {1..10}; do
echo $num
done
# 带步长的序列
for num in {0..100..10}; do
echo $num
done
while 循环
#!/bin/bash
# 基本 while 循环
count=1
while [ $count -le 5 ]; do
echo "计数: $count"
((count++))
done
# 读取文件
while IFS= read -r line; do
echo "行内容: $line"
done < /etc/hosts
# 无限循环
while true; do
echo "按 Ctrl+C 退出"
sleep 1
done
until 循环
#!/bin/bash
count=1
until [ $count -gt 5 ]; do
echo "计数: $count"
((count++))
done
break 和 continue
#!/bin/bash
# break 跳出循环
for i in {1..10}; do
if [ $i -eq 5 ]; then
break
fi
echo $i
done
# continue 跳过本次循环
for i in {1..10}; do
if [ $i -eq 5 ]; then
continue
fi
echo $i
done
函数
函数定义和调用
#!/bin/bash
# 函数定义方式1
function greet() {
echo "Hello, $1!"
}
# 函数定义方式2
greet2() {
echo "Hi, $1!"
}
# 调用函数
greet "Linux"
greet2 "World"
# 带返回值的函数
add() {
local result=$(($1 + $2))
echo $result
}
sum=$(add 10 20)
echo "和: $sum"
# 使用 return 返回状态码
check_file() {
if [ -f "$1" ]; then
return 0
else
return 1
fi
}
if check_file "/etc/passwd"; then
echo "文件存在"
fi
局部变量和全局变量
#!/bin/bash
global_var="全局变量"
test_scope() {
local local_var="局部变量"
echo "函数内: $global_var"
echo "函数内: $local_var"
}
test_scope
echo "函数外: $global_var"
# echo "函数外: $local_var" # 错误:未定义
实用技巧
命令替换
#!/bin/bash
# 反引号(旧式)
date=`date +%Y%m%d`
# $() 推荐方式
date=$(date +%Y%m%d)
hostname=$(hostname)
echo "备份文件: backup_${hostname}_${date}.tar.gz"
参数展开
#!/bin/bash
# 默认值
echo "${var:-default}" # 如果 var 未设置,使用 default
echo "${var:=default}" # 如果 var 未设置,设置为 default
echo "${var:+alternate}" # 如果 var 已设置,使用 alternate
echo "${var:?error message}" # 如果 var 未设置,显示错误并退出
Here Document
#!/bin/bash
# 多行输入
cat << EOF > config.txt
Server: production
Port: 8080
Debug: false
EOF
# 变量展开
cat << EOF
当前用户: $USER
当前目录: $PWD
EOF
# 禁止变量展开
cat << 'EOF'
原样输出: $USER
EOF
进程替换
#!/bin/bash
# 比较两个命令的输出
diff <(ls dir1) <(ls dir2)
# 将命令输出作为文件
while read line; do
echo "行: $line"
done < <(ls -l)
调试技巧
#!/bin/bash
# 启用调试模式
set -x # 打印执行的命令
set -e # 遇到错误立即退出
set -u # 使用未定义变量时报错
set -o pipefail # 管道中任一命令失败则失败
# 组合使用
set -euo pipefail
# 调试函数
debug() {
if [ "${DEBUG:-0}" = "1" ]; then
echo "[DEBUG] $@" >&2
fi
}
# 使用
debug "This is a debug message"
# 运行时启用调试
# DEBUG=1 ./script.sh
下一步:学习 高级脚本技巧 章节。