数据类型 #

一、Shell数据类型概述 #

Shell是一种弱类型语言,变量不需要预先声明类型。Shell主要支持以下数据类型:

类型 说明 示例
字符串 文本数据 “hello”
数字 整数运算 123
数组 数据集合 (a b c)
关联数组 键值对 ([key]=value)

二、字符串 #

2.1 字符串定义 #

bash
# 单引号字符串
str1='Hello World'

# 双引号字符串(支持变量替换)
name="张三"
str2="你好, $name"

# 无引号字符串(不推荐)
str3=Hello

# 多行字符串
str4="第一行
第二行
第三行"

# Here Document
str5=$(cat <<EOF
这是多行文本
可以包含变量: $name
EOF
)

2.2 单引号与双引号 #

bash
name="张三"

# 单引号:原样输出
echo '你好, $name'    # 输出: 你好, $name

# 双引号:变量替换
echo "你好, $name"    # 输出: 你好, 张三

# 转义字符
echo "换行\n制表\t"   # 输出: 换行\n制表\t
echo -e "换行\n制表\t" # 输出: 换行
                         #      制表    

2.3 字符串操作 #

bash
str="Hello World"

# 获取长度
echo ${#str}           # 输出: 11

# 拼接字符串
str1="Hello"
str2="World"
result="${str1} ${str2}"
echo "$result"         # 输出: Hello World

# 截取子串
str="Hello World"
echo ${str:0:5}        # 输出: Hello
echo ${str:6}          # 输出: World
echo ${str: -5}        # 输出: World(注意空格)

# 查找子串
str="Hello World"
echo ${str#Hello}      # 输出:  World
echo ${str%World}      # 输出: Hello 

2.4 字符串替换 #

bash
str="hello world world"

# 替换第一个匹配
echo ${str/world/WORLD}    # 输出: hello WORLD world

# 替换所有匹配
echo ${str//world/WORLD}   # 输出: hello WORLD WORLD

# 删除匹配
echo ${str//world/}        # 输出: hello  

# 从开头删除
str="hello.txt"
echo ${str%.txt}           # 输出: hello

# 从结尾删除
str="/path/to/file.txt"
echo ${str##*/}            # 输出: file.txt

三、数字 #

3.1 整数 #

Shell原生只支持整数运算:

bash
# 定义整数
num=42

# 算术运算
echo $((num + 10))     # 输出: 52
echo $((num - 10))     # 输出: 32
echo $((num * 2))      # 输出: 84
echo $((num / 5))      # 输出: 8
echo $((num % 5))      # 输出: 2

# 自增自减
count=0
((count++))
echo $count            # 输出: 1
((count--))
echo $count            # 输出: 0

3.2 算术运算方式 #

bash
# 方式一:$(())
result=$((5 + 3))
echo $result           # 输出: 8

# 方式二:let
let result=5+3
echo $result           # 输出: 8

# 方式三:expr
result=$(expr 5 + 3)
echo $result           # 输出: 8

# 方式四:bc(支持浮点)
result=$(echo "5.5 + 3.3" | bc)
echo $result           # 输出: 8.8

3.3 浮点数运算 #

Shell原生不支持浮点数,需要使用bc或awk:

bash
# 使用bc
result=$(echo "scale=2; 10 / 3" | bc)
echo $result           # 输出: 3.33

# 使用awk
result=$(awk 'BEGIN{printf "%.2f", 10/3}')
echo $result           # 输出: 3.33

# 比较浮点数
a=3.14
b=3.15
if (( $(echo "$a < $b" | bc -l) )); then
    echo "$a 小于 $b"
fi

3.4 数字进制 #

bash
# 二进制
binary=2#1010
echo $binary           # 输出: 10

# 八进制
octal=8#12
echo $octal            # 输出: 10

# 十六进制
hex=16#A
echo $hex              # 输出: 10

# 进制转换
echo $((16#FF))        # 输出: 255
echo "obase=2; 10" | bc # 输出: 1010

四、数组 #

4.1 普通数组 #

bash
# 定义数组
arr=(1 2 3 4 5)

# 访问元素
echo ${arr[0]}         # 输出: 1
echo ${arr[2]}         # 输出: 3

# 所有元素
echo ${arr[@]}         # 输出: 1 2 3 4 5
echo ${arr[*]}         # 输出: 1 2 3 4 5

# 数组长度
echo ${#arr[@]}        # 输出: 5

# 添加元素
arr+=(6 7)
echo ${arr[@]}         # 输出: 1 2 3 4 5 6 7

# 删除元素
unset arr[2]
echo ${arr[@]}         # 输出: 1 2 4 5 6 7

4.2 数组操作 #

bash
# 定义数组
arr=(apple banana cherry date)

# 遍历数组
for item in "${arr[@]}"; do
    echo "水果: $item"
done

# 带索引遍历
for i in "${!arr[@]}"; do
    echo "索引 $i: ${arr[$i]}"
done

# 切片
echo ${arr[@]:1:2}     # 输出: banana cherry

# 查找元素
if [[ " ${arr[@]} " =~ " banana " ]]; then
    echo "找到banana"
fi

# 数组拼接
arr1=(1 2 3)
arr2=(4 5 6)
arr3=("${arr1[@]}" "${arr2[@]}")
echo ${arr3[@]}        # 输出: 1 2 3 4 5 6

4.3 关联数组 #

bash
# 声明关联数组
declare -A user

# 设置键值对
user[name]="张三"
user[age]=25
user[city]="北京"

# 访问元素
echo ${user[name]}     # 输出: 张三
echo ${user[age]}      # 输出: 25

# 所有键
echo ${!user[@]}       # 输出: name age city

# 所有值
echo ${user[@]}        # 输出: 张三 25 北京

# 遍历
for key in "${!user[@]}"; do
    echo "$key: ${user[$key]}"
done

# 数组长度
echo ${#user[@]}       # 输出: 3

五、类型判断与转换 #

5.1 类型判断 #

bash
# 判断是否为数字
is_number() {
    [[ "$1" =~ ^[0-9]+$ ]]
}

is_number "123" && echo "是数字"
is_number "abc" || echo "不是数字"

# 判断是否为整数
is_integer() {
    [[ "$1" =~ ^-?[0-9]+$ ]]
}

# 判断是否为浮点数
is_float() {
    [[ "$1" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]
}

5.2 字符串转数字 #

bash
# 字符串转整数
str="123"
num=$((str))
echo $num              # 输出: 123

# 使用expr
num=$(expr "$str" + 0)

# 使用bc
float_str="3.14"
float_num=$(echo "$float_str" | bc)
echo $float_num        # 输出: 3.14

5.3 数字转字符串 #

bash
# 数字本身就是字符串形式
num=123
str="$num"
echo $str              # 输出: 123

# 格式化输出
num=42
str=$(printf "%05d" $num)
echo $str              # 输出: 00042

六、特殊数据结构 #

6.1 只读变量 #

bash
# 声明只读变量
readonly PI=3.14159

# 或
declare -r PI=3.14159

# 尝试修改会报错
PI=3.14    # 报错: PI: readonly variable

6.2 整数变量 #

bash
# 声明整数变量
declare -i count
count=10
count="hello"          # 自动转换为0
echo $count            # 输出: 0

# 整数变量自动计算
declare -i num
num=5+3
echo $num              # 输出: 8

6.3 数组变量 #

bash
# 声明数组
declare -a arr
arr=(1 2 3)

# 声明关联数组
declare -A map
map[key]=value

6.4 导出变量 #

bash
# 声明并导出
declare -x MY_VAR="value"

# 等同于
export MY_VAR="value"

七、实战示例 #

7.1 配置文件解析 #

bash
#!/bin/bash

# 配置文件格式: key=value
parse_config() {
    local config_file="$1"
    declare -A config
    
    while IFS='=' read -r key value; do
        # 跳过注释和空行
        [[ "$key" =~ ^#.*$ || -z "$key" ]] && continue
        
        # 去除前后空格
        key=$(echo "$key" | xargs)
        value=$(echo "$value" | xargs)
        
        config["$key"]="$value"
    done < "$config_file"
    
    # 返回配置
    for key in "${!config[@]}"; do
        echo "$key=${config[$key]}"
    done
}

parse_config "config.conf"

7.2 数据处理脚本 #

bash
#!/bin/bash

# 处理CSV数据
process_csv() {
    local csv_file="$1"
    declare -a headers
    declare -a rows
    
    # 读取表头
    IFS=',' read -ra headers <<< "$(head -n 1 "$csv_file")"
    
    # 读取数据行
    while IFS=',' read -ra row; do
        rows+=("$(IFS=','; echo "${row[*]}")")
    done < <(tail -n +2 "$csv_file")
    
    # 显示数据
    echo "表头: ${headers[*]}"
    echo "行数: ${#rows[@]}"
}

process_csv "data.csv"

7.3 类型安全函数 #

bash
#!/bin/bash

# 类型安全的加法函数
safe_add() {
    local a="$1"
    local b="$2"
    
    # 验证输入
    if ! [[ "$a" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
        echo "错误: $a 不是有效数字" >&2
        return 1
    fi
    
    if ! [[ "$b" =~ ^-?[0-9]+(\.[0-9]+)?$ ]]; then
        echo "错误: $b 不是有效数字" >&2
        return 1
    fi
    
    # 执行加法
    echo "$a + $b" | bc
}

safe_add "3.14" "2.86"

八、总结 #

8.1 数据类型要点 #

类型 说明 操作
字符串 文本数据 ${#str}, $
数字 整数 $(()), let, expr
数组 索引数组 ${arr[@]}, $
关联数组 键值对 declare -A, $

8.2 类型声明 #

bash
declare -r var=value    # 只读
declare -i var=value    # 整数
declare -a var=()       # 数组
declare -A var=()       # 关联数组
declare -x var=value    # 导出

8.3 下一步 #

你已经掌握了Shell的数据类型,接下来让我们学习 算术运算符,深入了解Shell中的运算操作!

最后更新:2026-03-27