Linux命令-read(Bash 内建读取输入)
快速参考 :read 是 Bash 内建命令,用于从标准输入读取一行数据并存入一个或多个变量。read 是 Shell 脚本交互式编程的核心,支持超时、静默输入、数组读取等高级特性,是编写用户友好脚本的必备工具。
提示 :
read是 Bash 内建命令(type read显示read is a shell builtin),执行速度极快,无需额外进程。
命令语法
bash
read [选项] [变量名 ...]
常用选项
| 选项 | 说明 |
|---|---|
-p "提示" |
显示提示信息 |
-t 秒数 |
超时时间,超时返回非零退出码 |
-s |
静默模式,输入不显示(适合密码) |
-a 数组名 |
将输入按单词存入索引数组 |
-n 字符数 |
读取指定字符数后自动结束 |
-r |
不转义反斜杠(推荐始终使用) |
-e |
使用 Readline 库(支持行编辑) |
-d 分隔符 |
用指定字符作为行结束符 |
-N 字符数 |
读取指定字符数(忽略分隔符) |
-u fd |
从指定文件描述符读取 |
场景化实例
1. 基本交互式输入
bash
#!/bin/bash
# 简单交互示例
echo "请输入您的姓名:"
read name
echo "您好,$name!欢迎使用本系统。"
# 使用 -p 一步完成
read -p "请输入您的年龄:" age
echo "年龄:$age 岁"
2. 密码静默输入
bash
#!/bin/bash
# 安全输入密码
read -s -p "请输入数据库密码:" db_pass
echo # 换行
read -s -p "请再次输入确认:" db_pass_confirm
echo
if [ "$db_pass" != "$db_pass_confirm" ]; then
echo "两次输入不一致!"
exit 1
fi
echo "密码设置成功"
3. 带超时的输入
bash
#!/bin/bash
# 超时示例:5 秒内必须响应
read -t 5 -p "是否继续安装?(y/n) [默认 y]:" choice
exit_code=$?
if [ $exit_code -ne 0 ]; then
echo -e "\n超时未响应,默认继续安装"
choice="y"
fi
case "$choice" in
y|Y|"") echo "开始安装..." ;;
n|N) echo "已取消安装"; exit 0 ;;
*) echo "无效输入"; exit 1 ;;
esac
4. 读取到数组
bash
#!/bin/bash
# 读取多个单词到数组
read -p "请输入服务器列表(空格分隔):" -a servers
echo "共输入 ${#servers[@]} 台服务器:"
for i in "${!servers[@]}"; do
echo " [$i] ${servers[$i]}"
done
# 遍历执行任务
for server in "${servers[@]}"; do
echo "正在连接 $server ..."
done
5. 限制读取字符数
bash
#!/bin/bash
# 菜单选择:只需按一个键
read -n 1 -p "请选择操作 [A]添加 [D]删除 [Q]退出:" option
echo
case "$option" in
a|A) echo "执行添加操作" ;;
d|D) echo "执行删除操作" ;;
q|Q) echo "再见!"; exit 0 ;;
*) echo "无效选项" ;;
esac
6. 解析配置文件
bash
#!/bin/bash
# 读取配置文件(格式: KEY=VALUE)
config_file="/etc/myapp/settings.conf"
while IFS='=' read -r key value; do
# 跳过空行和注释
[[ -z "$key" || "$key" =~ ^# ]] && continue
# 去除首尾空格
key=$(echo "$key" | xargs)
value=$(echo "$value" | xargs)
echo "配置项: $key = $value"
declare "$key=$value"
done < "$config_file"
7. 使用 -r 避免反斜杠转义
bash
#!/bin/bash
# 对比 -r 的影响
echo "测试不含 -r:"
echo "第一行\n第二行" | while read line; do
echo "读取到: $line"
done
echo "测试含 -r:"
echo "第一行\n第二行" | while read -r line; do
echo "读取到: $line"
done
# -r 模式下 \n 保持原样,被视为字面字符
8. 实际脚本:用户注册向导
bash
#!/bin/bash
# 多步骤交互式注册脚本
echo "===== 用户注册向导 ====="
read -p "用户名(字母数字,3-20位):" username
if [[ ! "$username" =~ ^[a-zA-Z0-9_]{3,20}$ ]]; then
echo "用户名格式不正确!"
exit 1
fi
read -s -p "密码(至少8位):" password
echo
if [ ${#password} -lt 8 ]; then
echo "密码长度不足!"
exit 1
fi
read -p "邮箱地址:" email
read -t 10 -p "输入验证码(10秒内,按回车跳过):" captcha
echo
echo "注册信息确认:"
echo " 用户名: $username"
echo " 邮箱: $email"
echo " 密码: ****"
read -n 1 -p "确认提交?(Y/n):" confirm
echo
if [[ "$confirm" == "y" || "$confirm" == "Y" || "$confirm" == "" ]]; then
echo "注册成功!"
fi
退出状态
bash
# read 退出码检测
read -t 3 -p "输入:" input
case $? in
0) echo "正常读取: $input" ;;
1) echo "遇到 EOF" ;;
142) echo "超时" ;; # 128 + 14(SIGALRM)
esac
最佳实践
始终使用
-r:防止反斜杠被意外转义。IFS=配合read可保留行首尾空白。
bash
# 推荐写法:安全读取文件每一行
while IFS= read -r line || [[ -n "$line" ]]; do
echo "处理: $line"
done < input.txt
# 避免的写法(丢失反斜杠)
while read line; do
echo "$line"
done < input.txt