变量与数据类型:字符串、数字、数组
Shell 里一切以字符串处理居多,算术、数组、关联数组则各有约定写法。
一、变量基础
Shell 变量是在 Shell 环境中存储数据的命名容器,用于在脚本或交互会话里传递和操作数据。
定义与赋值
shell
变量名=变量值
# 示例
name="David"
readonly age=18 # 只读,后续不可改
# 注意
# - 等号两侧不能有空格
# - 变量名只能包含字母、数字、下划线,且不能以数字开头
# - 值含空格时必须引号括起来;纯字符串且无空格时有时可省略引号,但不推荐依赖省略读取变量
shell
echo $name
echo ${name} # 推荐:边界清晰
# 拼接时 ${name} 更安全,例如:
echo "Hello, ${name}Script"删除变量
shell
unset name默认值与兜底(兼容性常用)
shell
${变量名:-默认值} # 未定义或为空时返回默认值,不赋值
${变量名:=默认值} # 未定义或为空时赋默认值并返回
echo ${name:-"Unknown"}环境变量与局部变量
环境变量:被子进程继承;常用 export。
shell
export PATH=$PATH:/新路径
export LANG=en_US.UTF-8
env
printenv
set # 所有变量(含 shell 选项)
set -u # 使用未定义变量时报错,避免默默为空局部变量(函数内):
shell
my_func() {
local x=10
echo $x
}常用内置/环境相关变量
shell
$HOME # 用户主目录
$PWD # 当前工作目录
$USER # 当前用户
$SHELL # 当前 Shell 路径
$PATH # 命令搜索路径
$? # 上条命令退出码
$$ # 当前进程 ID
$0 # 脚本名
$1... # 参数
$# # 参数个数
$* / $@ # 全部参数二、字符串
包括:定义、长度、拼接、截取、替换、删除、子串判断、大小写。
单引号、双引号
- 单引号
'':强引用,不展开变量、不解释多数转义(单引号内不能再写单引号作为内容,需换写法)。 - 双引号
"":弱引用,会展开变量、命令替换与部分转义。
shell
name="world"
str='hello $name' # 字面量 hello $name
str2="hello $name" # hello world长度、拼接
shell
str="test"
echo ${#str} # 4
first="Hello"
last="World"
echo "$first$last"
echo "$first $last" # 含空格时务必加引号截取 ${var:offset:length}
索引从 0 开始;从末尾数可用负数,负索引前建议加空格,避免与默认值的 :- 语法冲突。
shell
str="abcdefghij"
echo ${str:2} # 从索引 2 到末尾
echo ${str:3:4} # 从 3 起 4 个字符
echo ${str: -2} # 最后两个字符(注意 -2 前空格)替换
shell
str="apple banana apple cherry"
# 只换第一个
echo ${str/apple/APPLE}
# 全部替换
echo ${str//apple/APPLE}
# 行首/行尾
echo ${str/#apple/FRUIT}
echo ${str/%cherry/FRUIT}
# 删成空
echo ${str//banana/}删前缀/后缀(# ## % %%)
shell
file_path="/home/user/documents/report.txt"
echo ${file_path##*/} # 文件名:report.txt
echo ${file_path%.txt} # 去最后一个 .txt
echo ${file_path%/*} # 目录部分
echo ${file_path#/home/} # 去最短前缀 /home/是否包含子串、查位置
shell
# 是否包含(Bash [[ ]]
[[ $str == *子串* ]]
# 位置:expr
expr index "$str" 子串
# 或 awk
awk -v str="$str" -v sub="world" 'BEGIN{print index(str, sub)}' </dev/null大小写(借助 tr / awk)
shell
str="Hello World"
echo $str | tr 'a-z' 'A-Z'
echo $str | tr 'A-Z' 'a-z'三、数字与运算
Shell 中数字处理分整数与浮点;Bash 对整数有原生支持,浮点常靠 bc 或 awk。
整数:推荐 $(( ))
shell
a=10
b=3
echo $((a + b))
echo $((a * b)) # * 在 (( )) 内不必转义
echo $((a / b)) # 整除
echo $((a % b))
# 幂:Bash 4+ 支持 **
echo $((a ** 2))expr(老用法,易踩坑,仅作了解):
shell
expr $a + $b
expr $a \* $b # * 要转义let(赋值与自增):
shell
let a=a*2+3
let a++浮点:bc / awk
shell
echo "2.5 + 3.8" | bc
echo "scale=2; 10 / 3" | bc
awk -v a=2.5 -v b=3.8 'BEGIN{print a + b}'
awk -v a=10 -v b=3 'BEGIN{printf "%.2f\n", a / b}'比较
整数在 [ ] / test 中用:-eq -ne -gt -lt -ge -le。
shell
if [ $a -gt $b ]; then
echo "$a > $b"
fi浮点需借助工具:
shell
if [ $(echo "$a > $b" | bc) -eq 1 ]; then
echo "a 大于 b"
fi示例片段(保留原教学意图)
shell
# 1+...+100
sum=0
for ((i=1; i<=100; i++)); do
sum=$((sum + i))
done
echo $sum注意事项
- 变量默认可当字符串;参与算术前应确保值为数字。
$((10/3))为整数除法;要小数用bc/awk。expr里*需转义;$(( ))里不需要。bc的scale主要影响除法等结果的精度展示。
四、数组
定义与访问
shell
arr=("元素1" "元素2" "元素3")
arr[0]="元素1"
arr+=("元素5")
echo ${arr[0]}
echo ${arr[@]} # 所有元素
echo ${#arr[@]} # 元素个数含空格元素遍历时务必:for x in "${arr[@]}"; do。
截取、拼接
shell
echo ${arr[@]:1:3}
arr1=("a" "b")
arr2=("c" "d")
arr3=("${arr1[@]}" "${arr2[@]}")关联数组(Bash 4+)
shell
declare -A dict
dict["key1"]="value1"
echo ${dict["key1"]}
echo ${!dict[@]} # 所有键
for key in "${!dict[@]}"; do
echo "$key: ${dict[$key]}"
done实用技巧
shell
# 元素是否在数组中(示意)
if [[ " ${arr[@]} " =~ " 元素2 " ]]; then
echo "存在"
fi
# 字符串按分隔符变数组
str="a,b,c"
IFS=, read -ra arr <<< "$str"五、与后续章节的衔接
- 流程判断里会大量使用
[ ]、[[ ]]与上文的字符串、数值比较。 - 函数、进程与环境变量配合见 函数·输入输出与环境协作。
- 错误码、
set -e、trap见 健壮性:错误处理、退出与模块引入。
