Shell脚本编程——变量、运算符、表达式和控制语句

Shell脚本编程

一、变量

1.1、变量第一与赋值

命名规则:

  • 以字母或下划线开头,由字母、数字和下划线组成。
  • 区分大小写(如var与VAR不同)。
  • 避免使用Shell关键字(如if, for)和特殊符号。

赋值语法:

var_name=value  # 等号两侧不能有空格!
# 值可以是字符串、数字或命令输出(使用$(command)或反引号 `command`)。

1.2、变量类型

  • 默认类型: 均为字符串,即使赋值为数字
  • 数值操作:
# 使用算术扩展
sum=$((1 + 2))
# 或 let 命令
let "sum = 1 + 2"

1.3、变量引用

  • 基本引用:$符号,如 echo $var
  • 避免歧义: 使用${var}(例如${var}_suffix
  • 执行命令: 使用``符号,该命令将会被执行
#! /bain/bash
log=Saturday
echo "Today is $log"
echo 'Today is$log'
echo "Today is `date`"

# 输出
Today is Saturday
Today is$log
Today is 20254月13日 星期日 22时40分06秒 CST

1.4、环境变量和局部变量

局部变量: 仅在当前Shell生效

local_val="value"

环境变量: 可被子进程继承

export GLOBAL_VAR="value"
# 或先赋值再导出
GLOBAL_VAR="value"
export GLOBAL_VAR

父Shell环境: 使用source命令可以强行让一个脚本影响其父Shell环境

# 脚本内容 varible.sh
#! /bin/bash
log="monday"
echo "The value of logfile is:"
echo $log

# 执行命令
source varible.sh

# 父环境执行
echo $log

1.5、特殊变量

变量描述
$0脚本名称
$1-$n位置参数(第1到第n个参数)
$#参数个数
$@所有参数(每个参数独立)
$*所有参数(合并)
$?上一条命令的退出状态
$$当前进程的PID
$!最后一个后台进程的PID

1.6、引号与变量扩展

双引号: 允许变量和转义字符扩展

echo "Value: $var"

单引号: 原样输出,不进行扩展

echo 'Value: $var'  # 输出:Value: $var

1.7、默认值处理

空值处理:

${var:-default}    # 若var未定义或为空,使用default
${var:=default}    # 同上,并将var赋值为default
${var:?error_msg}  # 若var为空,报错并终止脚本
${var:+alternate}  # 若var非空,使用alternate

1.8、字符串操作

与替换:

${var#pattern}     # 删除开头最短匹配
${var##pattern}    # 删除开头最长匹配
${var%pattern}     # 删除结尾最短匹配
${var%%pattern}    # 删除结尾最长匹配
${var/old/new}     # 替换第一个匹配
${var//old/new}    # 替换所有匹配

获取长度:

length=${#var}

1.9、数组

定义与访问:

array=("a" "b" "c")         # 索引数组
declare -A assoc_array      # 关联数组(Bash 4+)
assoc_array["key"]="value"

echo ${array[0]}            # 输出第一个元素
echo ${assoc_array["key"]}  # 输出键对应的值

数组操作:

${array[@]}    # 所有元素
${#array[@]}   # 数组长度
${!array[@]}   # 所有索引(关联数组为键)

1.10、只读变量与删除

只读变量:

readonly PI=3.14

删除变量:

unset var_name  # 不能删除只读变量

1.11、作用域

函数内局部变量:

func() {
  local local_var="value"  # 仅函数内有效
}

1.12、其它技巧

间接引用:

var="name"
name="Alice"
echo ${!var}  # 输出:Alice

读取用户输入:

read -p "Enter: " input_var

二、运算符

2.1、算数运算符

运算符描述示例结果
+加法echo $((5 + 3))8
-减法echo $((10 - 4))6
*乘法echo $((2 * 6))12
/除法echo $((20 / 3))6(取整数部分)
%取模echo $((10 % 3))1
**幂运算echo $((2 ​** 3))8(仅 Bash 支持)
++自增a=5; ((a++)); echo $a6
--自减a=5; ((a--)); echo $a4

用于整数计算,需用 $(( ))expr$[] 包裹(注意空格和语法差异)

echo $(expr 3 + 5)
echo $[3 + 5]
echo $((3 + 5))

2.2、比较运算符

2.2.1、数值比较

用于 if 条件判断,需用 -eq、-ne 等。

运算符描述示例
-eq等于if [ $a -eq $b ]
-ne不等于if [ $a -ne $b ]
-gt大于if [ $a -gt $b ]
-lt小于if [ $a -lt $b ]
-ge大于等于if [ $a -ge $b ]
-le小于等于if [ $a -le $b ]
#! /bin/bash
a=100
b=200
if [ $a -eq $b ]; then
	echo "-eq"
fi
if [ $a -ne $b ]; then
	echo "-ne"
fi
if [ $a -eq $b ]; then
	echo "-eq"
fi
if [ $a -eq $b ]; then
	echo "-eq"
fi
if [ $a -eq $b ]; then
	echo "-eq"
fi
if [ $a -eq $b ]; then
	echo "-eq"
fi
if [ $a -eq $b ]; then
	echo "-eq"
fi

2.2.2、字符串比较

用 =、!= 等,需用双括号 [[ ]] 或单括号 [ ]。

运算符描述示例
=字符串相等if [[ "$str1" = "$str2" ]]
!=字符串不等if [ "$str1" != "$str2" ]
>字典序大于if [[ "$str1" > "$str2" ]]
<字典序小于if [[ "$str1" < "$str2" ]]
-z字符串为空if [ -z "$str" ]
-n字符串非空if [ -n "$str" ]

注意:

  • 使用 [[ ]] 支持更多操作(如通配符 * 匹配)。
  • 字符串比较时变量建议用双引号包裹,避免空值错误。
#! /bin/bash
str1="aaa"
str2="bbb"
if [[ "$str1" = "$str2" ]]; then
	echo "="
fi
if [ "$str1" != "$str2" ]; then
	echo "!="
fi
if [[ "$str1" > "$str2" ]]; then
	echo ">"
fi
if [[ "$str1" < "$str2" ]]; then
	echo "<"
fi
if [ -z "$str" ]; then
	echo "null"
fi
if [ -n "$str" ]; then
	echo "not null"
fi

2.3、逻辑运算符

主要用于 if、while 等语句的条件判断,需在 [ ] 或 [[ ]] 中使用。

2.3.1、逻辑与(AND)

​- 符号:-a(单括号 [ ] 内使用)或 &&(双括号 [[ ]] 中)
​- 规则:所有条件为真时,整体为真。

# 单括号 [ ] 中使用 -a
if [ "$a" -gt 5 -a "$b" -lt 10 ]; then
  echo "a >5 且 b <10"
fi

# 双括号 [[ ]] 中使用 &&
if [[ "$a" > 5 && "$b" < 10 ]]; then
  echo "a >5 且 b <10"
fi

2.3.2、逻辑或(OR)

  • 符号:-o(单括号 [ ] 内使用)或 ||(双括号 [[ ]] 中)
    ​规则:任意条件为真时,整体为真。
# 单括号 [ ] 中使用 -o
if [ "$x" = "yes" -o "$x" = "y" ]; then
  echo "x 是 yes 或 y"
fi

# 双括号 [[ ]] 中使用 ||
if [[ "$x" == "yes" || "$x" == "y" ]]; then
  echo "x 是 yes 或 y"
fi

2.3.3、逻辑非(NOT)

  • ​符号:!
  • ​规则:反转条件的真假值。
if [ ! -f "file.txt" ]; then
  echo "file.txt 不存在"
fi

2.3.4、命令执行中的逻辑运算符

逻辑与&&
前一个命令执行成功(退出状态码 0),才执行下一个命令

mkdir dir && cd dir    # 创建目录成功后进入

逻辑或 ||
前一个命令执行失败(非 0 状态码),才执行下一个命令。

rm file.txt || echo "删除失败"  # 删除失败时输出提示

2.3.5、不同括号的差异

单括号 [ ](test 命令的别名)​

  • 必须严格使用空格分隔元素:[ "$a" -eq 5 ]
  • 逻辑运算符必须用 -a(AND)和 -o(OR)
if [[ "$str" == *linux* && ${#str} -gt 10 ]]; then
  echo "字符串包含 linux 且长度超过10"
fi

双括号 [[ ]](Bash 扩展语法)​

  • 支持更灵活的条件表达式(如通配符匹配、正则表达式)
  • 逻辑运算符直接使用 && 和 ||
if [[ "$str" == *linux* && ${#str} -gt 10 ]]; then
  echo "字符串包含 linux 且长度超过10"
fi

2.3.6、复合条件与分组

使用括号分组条件,在 [[ ]] 中可用 ( ) 分组条件:

if [[ ($a -gt 5 || $a -lt -5) && $b == "ok" ]]; then
  echo "条件满足"
fi

多条件组合示例

if [[ -f "file.txt" && (! -d "backup" || -w ".") ]]; then
  echo "file.txt 存在,且(backup 不是目录 或 当前目录可写)"
fi

2.3.7、综合示例

#!/bin/bash

# 示例1:文件存在且可写时备份
file="data.txt"
backup_dir="backup"

if [[ -f "$file" && -w "$file" ]]; then
  mkdir -p "$backup_dir" || { echo "无法创建备份目录"; exit 1; }
  cp "$file" "$backup_dir" && echo "备份成功"
else
  echo "文件不存在或不可写"
fi

# 示例2:检查数字范围或字符串内容
input=$1

if [[ ($input -ge 1 && $input -le 10) || "$input" == "debug" ]]; then
  echo "输入有效"
else
  echo "输入无效"
fi

2.4、文件测试运算符

用于检查文件或目录的属性。

运算符描述示例
-b是否为块设备文件if [ -b $file ]
-c是否为字符设备文件if [ -c $file ]
-e文件/目录存在if [ -e "/path" ]
-f是普通文件(非目录/设备)if [ -f "file.txt" ]
-d是目录if [ -d "/tmp" ]
-g检测文件是否设置了SGID位if [ -g $file ]
-k检测文件是否设置了粘着位(Sticky Bit)if [ -k $file ]
-p检测文件是否是有名管道if [ -p $file ]
-u检测文件是否设置了SUID位if [ -u $file]
-s文件大小大于0字节if [ -s "data.log" ]
-r可读if [ -r "file.txt" ]
-w可写if [ -w "file.txt" ]
-x可执行if [ -x "script.sh" ]
-L是符号链接if [ -L "link" ]
-h同 -L(兼容性写法)if [ -h "link" ]
-N自上次读取后被修改过if [ -N "file.txt" ]
-S检测是否为Socketif [ -S $file ]

2.5、位运算符(仅限整数)

用于二进制位操作,需用 $(( ))。

运算符描述示例结果(二进制)
&按位与echo $((5 & 3))1(0101 & 0011)
|按位或echo $((5 | 3))7(0101 | 0011)
^按位异或echo $((5 ^ 3))6(0101 ^ 0011)
~按位取反echo $((~5)) -6(补码表示)
<<左移echo $((5 << 1))10(0101 → 1010)
>>右移echo $((5 >> 1))2(0101 → 0010)

2.6、赋值运算符

简化算术操作,需用 $(( )) 或 let。

运算符描述示例
=直接赋值a=10
+=加法赋值((a += 5)) → a=15
-=减法赋值let "a -= 3" → a=12
*=乘法赋值((a *= 2)) → a=24
/=除法赋值let "a /= 4" → a=6
%=取模赋值((a %= 5)) → a=1
#! /bin/bash
echo $((5 & 3))
echo $((5 | 3))
echo $((5 ^ 3))
echo $((~5))
echo $((5 << 1))
echo $((5 >> 1))

2.7、运算符优先级

  1. ()(括号)
  2. ++, --(自增/自减)
  3. **(幂运算)
  4. !, ~(逻辑非、按位取反)
  5. *, /, %
  6. +, -
  7. <<, >>
  8. &, ^, |
  9. =, +=, -= 等赋值运算符

2.8、综合示例

#!/bin/bash

# 算术运算
a=$(( (2 + 3) * 4 ))  # 20
echo "a = $a"

# 字符串比较
str1="hello"
str2="world"
if [[ "$str1" != "$str2" ]]; then
  echo "字符串不同"
fi

# 文件存在性检查
if [ -f "/etc/passwd" ]; then
  echo "/etc/passwd 存在"
fi

# 逻辑组合
num=15
if [[ $num -gt 10 && $num -lt 20 ]]; then
  echo "$num 在 10 和 20 之间"
fi

# 位运算
b=$(( 5 << 1 ))  # 10
echo "5左移1位: $b"

2.9、注意事项

  • 空格敏感:[ $a -eq $b ] 中括号内必须保留空格。
  • ​变量引用:建议用双引号包裹变量(如 “$var”),避免空值或空格导致的错误
  • ​整数限制:Shell 默认只处理整数,浮点运算需依赖 bc 或 awk。
  • ​兼容性:[[ ]] 是 Bash 扩展语法,传统 Shell 使用 [ ]

三、表达式求值

3.1、条件判断表达式

test命令([])

  • 语法:[ 表达式 ](括号内必须保留空格)。
  • 用途:检查文件属性、字符串和数值比较(兼容所有 Shell)。
# 文件存在性检查
[ -f "file.txt" ] && echo "文件存在"

# 数值比较
a=10
[ "$a" -eq 10 ] && echo "a 等于 10"

# 字符串比较
[ "$str" = "hello" ] && echo "字符串为 hello"

双括号[[]] (Bash扩展)

  • ​语法:[[ 表达式 ]],支持更灵活的运算符和模式匹配。
  • 优势:支持 &&|| 逻辑符,无需转义 <>
# 正则匹配
[[ "hello123" =~ ^[a-z]+[0-9]+$ ]] && echo "匹配成功"

# 复合条件
[[ $a -gt 5 && $b -lt 20 ]] && echo "条件成立"

3.2、数值运算表达式

算术扩展 $(())

  • 语法:$(( 表达式 )),直接计算数学表达式。
  • ​支持操作:+ - * / % ​** 等。
result=$(( 2 * (3 + 5) ))  # 结果为 16
echo $(( 10 % 3 ))          # 输出 1

# 自增操作
a=5
echo $(( a++ ))             # 输出 5,之后 a=6

** let 命令 **

  • ​语法:let 表达式,直接修改变量值。
let "a = 5 + 3"     # a=8
let "b = 2 ​** 4"    # b=16(幂运算)
let "c += 10"       # c 自增 10

** expr 命令 **

  • 语法:expr 表达式,用于简单数值或字符串操作。
  • 注意:运算符必须用空格分隔,* 需转义为 \*
sum=$(expr 5 + 3)    # 输出 8
len=$(expr length "hello")  # 字符串长度计算(非所有 Shell 支持)

3.3、字符串操作表达式

字符串拼接:

  • 语法:直接拼接,无需运算符。
str1="Hello, "
str2="World!"
combined="$str1$str2"  # 结果为 "Hello, World!"

** 子字符串提取:**

  • 语法:${变量:起点:长度}
str="abcdefgh"
echo ${str:2:3}     # 从索引2开始取3字符 → "cde"

字符串长度:

  • 语法:$(#变量)
str="hello"
echo ${#str}        # 输出 5

模式匹配与替换:

删除前缀/后缀

path="/home/user/file.txt"
echo ${path#*/}     # 删除第一个 / 前内容 → "home/user/file.txt"
echo ${path##*/}    # 删除最后一个 / 前内容 → "file.txt"
echo ${path%.*}     # 删除后缀 → "/home/user/file"

综合实例:

#!/bin/bash

# 条件判断与数值运算
num=15
if [[ "$num" =~ ^[0-9]+$ && $((num % 2)) -eq 0 ]]; then
    echo "$num 是偶数"
else
    echo "$num 是奇数或非纯数字"
fi

# 字符串操作与文件检查
file="data.log"
backup_dir="/backup"

if [[ -f "$file" && -w "$backup_dir" ]]; then
    cp "$file" "$backup_dir/${file%.*}_$(date +%F).log"
    echo "备份成功"
fi

# 使用 let 修改变量
counter=0
let "counter += 1"
echo "计数器值: $counter"

四、控制语句

4.1、条件判断语句(if / elif / else)

基础语法:

if [ 条件 ]; then
    # 条件为真时执行
elif [ 其他条件 ]; then
    # 其他条件为真时执行
else
    # 所有条件为假时执行
fi

示例:

#!/bin/bash
num=10

if [ "$num" -gt 15 ]; then
    echo "数字大于15"
elif [ "$num" -ge 10 ]; then
    echo "数字在10到15之间"
else
    echo "数字小于10"
fi

注意事项:

  • ​空格敏感:[ ] 内必须保留空格(如 [ “$a” -eq 5 ])。
  • 变量引用:变量建议用双引号包裹(如 “$var”),避免空值或空格问题。
  • 条件扩展:使用 [[ ]] 支持更复杂的条件(如正则匹配)

4.2、循环语句

4.2.1、for循环

语法:

for 变量 in 列表; do
    # 循环体
done

示例:

#!/bin/bash
# 遍历列表
for fruit in "apple" "banana" "orange"; do
    echo "水果: $fruit"
done

# 遍历文件
for file in *.txt; do
    echo "处理文件: $file"
done

# 遍历数字序列
for i in {1..5}; do
    echo "数字: $i"
done

# C语言风格(仅 Bash 支持)
for ((i=0; i<5; i++)); do
    echo "索引: $i"
done

4.2.2、while循环

语法:

while [ 条件 ]; do
    # 循环体(条件为真时执行)
done

示例:

#!/bin/bash
count=0

# 条件循环
while [ $count -lt 5 ]; do
    echo "计数: $count"
    ((count++))
done

# 读取文件内容
while read line; do
    echo "行内容: $line"
done < file.txt

# 无限循环(需手动退出)
while true; do
    echo "按 Ctrl+C 退出"
    sleep 1
done

4.2.3、until循环

语法:

until [ 条件 ]; do
    # 循环体(条件为假时执行)
done

示例:

#!/bin/bash
count=5

# 循环到条件为真时停止
until [ $count -eq 0 ]; do
    echo "倒计时: $count"
    ((count--))
done

4.2、分支选择语法(case)

语法:

case 变量 in
    模式1)
        # 匹配模式1时执行
        ;;
    模式2|模式3)
        # 匹配模式2或模式3时执行
        ;;
    *)
        # 默认情况
        ;;
esac

示例:

#!/bin/bash
os="Linux"

case "$os" in
    "Linux")
        echo "选择 Linux 系统"
        ;;
    "Windows"|"MacOS")
        echo "选择其他系统"
        ;;
    *)
        echo "未知系统"
        ;;
esac

模式匹配:

  • 支持通配符 *(任意字符)、?(单个字符)、[...](字符范围)。
  • 示例:匹配以 .sh 结尾的文件:
case "$file" in
    *.sh)
        echo "这是一个 Shell 脚本"
        ;;
esac

4.4、循环控制命令

4.4.1、break:立即退出当前循环

for i in {1..10}; do
    if [ $i -eq 5 ]; then
        break  # 退出循环
    fi
    echo "i: $i"
done

4.4.2、continue:跳过当前迭代,进入下一轮循环

for i in {1..5}; do
    if [ $i -eq 3 ]; then
        continue  # 跳过 i=3
    fi
    echo "数字: $i"
done

4.4.3、exit:退出整个脚本

if [ ! -f "required.txt" ]; then
    echo "文件缺失,退出脚本"
    exit 1
fi

4.5、高级控制技巧

4.5.1、条件与循环的组合

# 检查文件是否存在,若存在则逐行读取
if [ -f "data.txt" ]; then
    while read line; do
        echo "处理行: $line"
    done < data.txt
else
    echo "文件不存在"
fi

4.5.2、使用 select 创建菜单(仅 Bash 支持)

#!/bin/bash
PS3="请选择操作: "
options=("备份" "恢复" "退出")

select opt in "${options[@]}"; do
    case $opt in
        "备份")
            echo "执行备份..."
            ;;
        "恢复")
            echo "执行恢复..."
            ;;
        "退出")
            break
            ;;
        *)
            echo "无效选项"
            ;;
    esac
done

4.5.3、函数中的控制流

check_file() {
    if [ -f "$1" ]; then
        return 0  # 成功
    else
        return 1  # 失败
    fi
}

if check_file "config.ini"; then
    echo "配置文件存在"
fi

4.6、常见错误与调试

4.6.1、无限循环

错误示例:

while [ $var -lt 10 ]; do
    echo "变量未更新导致死循环"
done

# 确保循环条件中的变量会被修改

4.6.2、条件判断逻辑错误

错误示例:

if [ $num = 5 ]; then  # 若 $num 为空,等价于 [ = 5 ]
# 修复方法:始终引用变量:[ "$num" = 5 ]。

4.6.3、调试技巧

使用 set -x 启用调试模式:

#!/bin/bash
set -x  # 打印每条执行的命令
echo "调试开始"
set +x  # 关闭调试

五、read命令

read 是 Bash 中用于从标准输入(键盘或管道)读取用户输入的内置命令,通常用于交互式脚本中获取用户输入或处理文件数据。

5.1、基本使用

基本语法:

read [options] [variable_name]
  • variable_name​:存储输入值的变量(如果不指定,默认存入 REPLY 变量)
  • options​:控制读取行为的选项

常用选项:

选项说明
-p "提示信息"显示提示信息(类似 echo -n + read)
-s静默模式(输入内容不显示,适用于密码)
-n 数字只读取指定字符数后自动继续
-t 秒数设置超时时间(超时后返回非零状态)
-a 数组名将输入按空格分割存入数组
-r禁用反斜杠转义(默认会解释 \)
-d 分隔符指定输入结束的分隔符(默认是换行符 \n)

5.2、用法示例

读取输入并存入变量:

read name
echo "你输入的名字是: $name"

# 运行
$ ./script.sh
John
你输入的名字是: John

使用-p显示提示信息:

read -p "请输入你的年龄: " age
echo "年龄: $age"

# 运行
$ ./script.sh
请输入你的年龄: 25
年龄: 25

静默输入(适用于密码):

read -s -p "请输入密码: " password
echo -e "\n你输入的密码是: [隐藏]"

# 运行
$ ./script.sh
请输入密码: 
你输入的密码是: [隐藏]

限制输入字符数-n:

read -n 5 -p "请输入5个字符: " text
echo -e "\n你输入的是: $text"

# 运行
$ ./script.sh
请输入5个字符: abcde
你输入的是: abcde

设置超时-t:

if read -t 5 -p "5秒内输入你的名字: " name; then
    echo "你好, $name!"
else
    echo -e "\n超时未输入!"
fi

# 运行
$ ./script.sh
5秒内输入你的名字: 
超时未输入!

读取输入到数组-a:

read -a fruits -p "输入几种水果(空格分隔): "
echo "你输入的水果有: ${fruits[0]}, ${fruits[1]}, ..."

# 运行
$ ./script.sh
输入几种水果(空格分隔): apple banana orange
你输入的水果有: apple, banana, orange

禁用反斜杠转义-r:

read -r -p "输入带反斜杠的字符串: " text
echo "你输入的是: $text"

# 运行
$ ./script.sh
输入带反斜杠的字符串: hello\nworld
你输入的是: hello\nworld

自定义输入结束符-d:

read -d ';' -p "输入一段话(以分号结束): " sentence
echo "你输入的是: $sentence"

# 运行
$ ./script.sh
输入一段话(以分号结束): 这是一段话;
你输入的是: 这是一段话

5.3、高级用法

从文件读取(结合while):

while read line; do
    echo "行内容: $line"
done < file.txt

读取多个变量:

read -p "输入姓名和年龄: " name age
echo "姓名: $name, 年龄: $age"

# 运行
$ ./script.sh
输入姓名和年龄: John 25
姓名: John, 年龄: 25

默认变量REPLY:
如果不指定变量名,输入内容会存入 REPLY:

read -p "输入任意内容: "
echo "你输入的是: $REPLY"

结合IFS(内部字段分隔符):

IFS=":" read -p "输入用户名和密码(用:分隔): " user pass
echo "用户名: $user, 密码: $pass"

# 运行
$ ./script.sh
输入用户名和密码(用:分隔): admin:123456
用户名: admin, 密码: 123456

5.4、注意事项

默认会去除前导和末尾空格,如果要保留,可以:

IFS= read -r line  # 保留所有空格和换行

read 会返回退出状态码​:

  • 0:成功读取
  • 非0:读取失败(如 EOF 或超时)

在管道中使用 read​:

echo "hello" | read var  # 可能不生效(子Shell问题)
echo "$var"  # 可能为空

# 替代方案
var=$(echo "hello")  # 使用命令替换

总结:

场景命令示例
基本输入read var
带提示read -p "提示" var
密码输入read -s -p "密码:" pass
超时控制read -t 5 -p "输入:" var
限制字符read -n 5 -p "输入5字符:" var
读取数组read -a arr -p "输入数组:"
从文件读取while read line; do ... done < file
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值