字符串运算符 #

一、字符串测试运算符 #

1.1 基本运算符 #

运算符 说明 示例
-z 字符串长度为零 [ -z “$str” ]
-n 字符串长度非零 [ -n “$str” ]
= 字符串相等 [ “$str1” = “$str2” ]
!= 字符串不相等 [ “$str1” != “$str2” ]
< 字典序小于 [[ “$str1” < “$str2” ]]
> 字典序大于 [[ “$str1” > “$str2” ]]

1.2 字符串长度测试 #

bash
#!/bin/bash

str=""
name="张三"

# 测试空字符串
if [ -z "$str" ]; then
    echo "str 是空字符串"
fi

# 测试非空字符串
if [ -n "$name" ]; then
    echo "name 不是空字符串: $name"
fi

# 另一种判断方式
if [ "$str" ]; then
    echo "str 非空"
else
    echo "str 为空"
fi

# 使用 [[ ]]
if [[ -z "$str" ]]; then
    echo "str 是空字符串"
fi

1.3 字符串相等测试 #

bash
#!/bin/bash

str1="hello"
str2="world"
str3="hello"

# 测试相等
if [ "$str1" = "$str3" ]; then
    echo "str1 等于 str3"
fi

# 测试不相等
if [ "$str1" != "$str2" ]; then
    echo "str1 不等于 str2"
fi

# 使用 [[ ]](推荐)
if [[ "$str1" == "$str3" ]]; then
    echo "str1 等于 str3"
fi

# 注意:= 和 == 在 [[ ]] 中等效
if [[ "$str1" = "$str3" ]]; then
    echo "str1 等于 str3"
fi

1.4 字符串大小比较 #

bash
#!/bin/bash

str1="apple"
str2="banana"

# 使用 [[ ]] 进行字典序比较
if [[ "$str1" < "$str2" ]]; then
    echo "$str1 在字典序上小于 $str2"
fi

if [[ "$str2" > "$str1" ]]; then
    echo "$str2 在字典序上大于 $str1"
fi

# 注意:在 [ ] 中需要转义
if [ "$str1" \< "$str2" ]; then
    echo "$str1 小于 $str2"
fi

二、字符串操作运算符 #

2.1 字符串长度 #

bash
#!/bin/bash

str="Hello World"

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

# 使用expr
expr length "$str"     # 输出: 11

# 使用wc
echo -n "$str" | wc -c # 输出: 11

# 使用awk
echo "$str" | awk '{print length}'

2.2 子串提取 #

bash
#!/bin/bash

str="Hello World"

# 从指定位置开始提取
echo ${str:6}          # 输出: World

# 提取指定长度
echo ${str:0:5}        # 输出: Hello

# 从右边开始提取
echo ${str: -5}        # 输出: World(注意空格)
echo ${str:(-5)}       # 输出: World

# 提取中间部分
echo ${str:6:5}        # 输出: World

2.3 子串删除 #

bash
#!/bin/bash

str="/usr/local/bin/python"

# 从左边删除最短匹配
echo ${str#*/}         # 输出: usr/local/bin/python

# 从左边删除最长匹配
echo ${str##*/}        # 输出: python

# 从右边删除最短匹配
echo ${str%/*}         # 输出: /usr/local/bin

# 从右边删除最长匹配
echo ${str%%/*}        # 输出: (空)

# 实际应用:获取文件名和扩展名
file="document.txt"
filename=${file%.*}    # document
extension=${file##*.}  # txt

2.4 子串替换 #

bash
#!/bin/bash

str="hello world world"

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

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

# 替换开头匹配
str="hello hello"
echo ${str/#hello/HELLO}   # 输出: HELLO hello

# 替换结尾匹配
str="hello world"
echo ${str/%world/WORLD}   # 输出: hello WORLD

三、字符串操作符总结 #

3.1 操作符一览 #

操作符 说明 示例
$ 字符串长度 $
$ 从start开始截取 $
$ 截取len个字符 $
$ 删除最短左边匹配 $
$ 删除最长左边匹配 $
$ 删除最短右边匹配 $
$ 删除最长右边匹配 $
$ 替换第一个 $
$ 替换所有 $
$ 替换开头 $
$ 替换结尾 $

3.2 默认值操作符 #

bash
#!/bin/bash

# 未定义则使用默认值
echo ${name:-"匿名"}        # 输出: 匿名

# 未定义则赋值并使用
echo ${username:="guest"}   # 输出: guest
echo $username              # 输出: guest

# 已定义则显示替代值
name="张三"
echo ${name:+"已定义"}      # 输出: 已定义

# 未定义则报错
# echo ${undefined:?"变量未定义"}  # 报错并退出

四、字符串处理函数 #

4.1 大小写转换 #

bash
#!/bin/bash

str="Hello World"

# 转小写(Bash 4.0+)
echo ${str,,}              # 输出: hello world

# 转大写(Bash 4.0+)
echo ${str^^}              # 输出: HELLO WORLD

# 首字母大写
echo ${str^}               # 输出: Hello world

# 使用tr命令
echo "$str" | tr '[:upper:]' '[:lower:]'  # 转小写
echo "$str" | tr '[:lower:]' '[:upper:]'  # 转大写

# 使用awk
echo "$str" | awk '{print tolower($0)}'   # 转小写
echo "$str" | awk '{print toupper($0)}'   # 转大写

4.2 字符串分割 #

bash
#!/bin/bash

# 使用IFS分割
str="apple,banana,cherry"
IFS=',' read -ra fruits <<< "$str"

for fruit in "${fruits[@]}"; do
    echo "水果: $fruit"
done

# 使用cut分割
echo "$str" | cut -d',' -f1  # 输出: apple
echo "$str" | cut -d',' -f2  # 输出: banana

# 使用awk分割
echo "$str" | awk -F',' '{print $1}'  # 输出: apple

4.3 字符串去空格 #

bash
#!/bin/bash

str="  hello world  "

# 去除两端空格
trimmed=$(echo "$str" | xargs)
echo "[$trimmed]"           # 输出: [hello world]

# 使用参数扩展
trimmed="${str#"${str%%[![:space:]]*}"}"  # 去前导空格
trimmed="${trimmed%"${trimmed##*[![:space:]]}"}"  # 去尾部空格
echo "[$trimmed]"

# 使用sed
trimmed=$(echo "$str" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
echo "[$trimmed]"

# 使用awk
trimmed=$(echo "$str" | awk '{$1=$1};1')
echo "[$trimmed]"

4.4 字符串查找 #

bash
#!/bin/bash

str="Hello World"

# 查找子串位置
if [[ "$str" == *"World"* ]]; then
    echo "找到 World"
fi

# 使用case
case "$str" in
    *World*)
        echo "找到 World"
        ;;
esac

# 使用grep
if echo "$str" | grep -q "World"; then
    echo "找到 World"
fi

# 获取子串位置
pos=$(expr index "$str" "World")
echo "World 位置: $pos"      # 输出: 7

五、实战示例 #

5.1 字符串验证函数 #

bash
#!/bin/bash

# 验证邮箱
validate_email() {
    local email="$1"
    
    if [[ ! "$email" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
        echo "无效邮箱格式"
        return 1
    fi
    
    echo "邮箱格式正确"
    return 0
}

# 验证手机号
validate_phone() {
    local phone="$1"
    
    if [[ ! "$phone" =~ ^1[3-9][0-9]{9}$ ]]; then
        echo "无效手机号格式"
        return 1
    fi
    
    echo "手机号格式正确"
    return 0
}

# 验证IP地址
validate_ip() {
    local ip="$1"
    
    if [[ "$ip" =~ ^([0-9]{1,3}\.){3}[0-9]{1,3}$ ]]; then
        local IFS='.'
        read -ra octets <<< "$ip"
        for octet in "${octets[@]}"; do
            if (( octet > 255 )); then
                echo "无效IP地址"
                return 1
            fi
        done
        echo "IP地址格式正确"
        return 0
    fi
    
    echo "无效IP地址格式"
    return 1
}

validate_email "test@example.com"
validate_phone "13800138000"
validate_ip "192.168.1.1"

5.2 字符串处理工具 #

bash
#!/bin/bash

# 生成随机字符串
random_string() {
    local length=${1:-16}
    tr -dc 'A-Za-z0-9' < /dev/urandom | head -c "$length"
}

# 生成UUID
generate_uuid() {
    cat /proc/sys/kernel/random/uuid
}

# 字符串加密(简单)
simple_encrypt() {
    local str="$1"
    echo "$str" | base64
}

# 字符串解密
simple_decrypt() {
    local str="$1"
    echo "$str" | base64 -d
}

# 使用示例
echo "随机字符串: $(random_string 8)"
echo "UUID: $(generate_uuid)"
encrypted=$(simple_encrypt "hello")
echo "加密: $encrypted"
echo "解密: $(simple_decrypt "$encrypted")"

5.3 路径处理函数 #

bash
#!/bin/bash

# 获取文件名
get_filename() {
    local path="$1"
    echo "${path##*/}"
}

# 获取目录名
get_dirname() {
    local path="$1"
    echo "${path%/*}"
}

# 获取文件扩展名
get_extension() {
    local path="$1"
    local filename="${path##*/}"
    echo "${filename##*.}"
}

# 获取不带扩展名的文件名
get_basename() {
    local path="$1"
    local filename="${path##*/}"
    echo "${filename%.*}"
}

# 使用示例
path="/home/user/documents/report.pdf"
echo "文件名: $(get_filename "$path")"
echo "目录名: $(get_dirname "$path")"
echo "扩展名: $(get_extension "$path")"
echo "基本名: $(get_basename "$path")"

六、字符串运算符速查表 #

6.1 测试运算符 #

运算符 说明 示例
-z 长度为零 [ -z “$str” ]
-n 长度非零 [ -n “$str” ]
= 相等 [ “$a” = “$b” ]
!= 不相等 [ “$a” != “$b” ]
< 小于 [[ “$a” < “$b” ]]
> 大于 [[ “$a” > “$b” ]]

6.2 操作运算符 #

操作符 说明
$ 长度
$ 截取
$ 删除左边最短
$ 删除左边最长
$ 删除右边最短
$ 删除右边最长
$ 替换第一个
$ 替换所有
$ 默认值

七、总结 #

7.1 关键要点 #

  • 使用 -z-n 测试字符串是否为空
  • 使用 =!= 比较字符串相等
  • 使用 ${#str} 获取字符串长度
  • 使用 ${str:start:len} 截取子串
  • 使用 ${str/old/new} 替换字符串

7.2 下一步 #

你已经掌握了字符串运算符,接下来让我们学习 文件测试运算符,了解Shell中的文件测试操作!

最后更新:2026-03-27