Linux read 命令详解:从标准输入读取变量的 shell 交互基石
Linux read 命令详解:从标准输入读取变量的 shell 交互基石
read 是 Linux Shell 内置命令,用于从键盘(标准输入)读取数据并赋值给变量,是编写交互式 Shell 脚本最基础、最高频的命令之一。本手册来自 linux-command 开源仓库的 command/read.md,本文在完整保留原文档全部实例的基础上,补充了选项语义、常见组合用法及仓库构建流程佐证,读完你可以直接写出带超时、带提示、能隐藏密码的交互式脚本。
命令概述
read 命令从键盘读取变量的值,通常用在 shell 脚本中与用户进行交互的场合。该命令可以一次读取多个变量的值,变量和输入的值都需要使用空格隔开。在 read 命令后面,如果没有指定变量名,读取的数据将被自动赋值给特定的内置变量 REPLY。
这意味着它不仅能实现"一问一答"的简单交互,还能通过一次读取、按空白拆分的方式,把一行输入中的多个字段分别装入多个变量,相当于为脚本提供了一条轻量的"输入解析"通道。
语法与选项
语法
read(选项)(参数)
选项
原文档明确给出的选项如下:
-p:指定读取值时的提示符;
-t:指定读取值时等待的时间(秒)。
结合原文档中的常用方式列表,实际使用中还会高频遇到以下选项:
-a:把输入的单词清单按空格拆分为数组元素,存入指定数组变量;
-n:只读取指定数量的字符,不需要按回车即可结束读取;
-d:用指定字符(而不是换行符)作为输入的结束定界符;
-r:允许输入包含反斜杠(不把反斜杠当作转义符处理);
-s:静默模式,输入不回显到终端(常用于密码读取)。
参数
变量:指定读取值的变量名。
不写变量名时,读取到的整行内容会被存入内置变量 REPLY;写多个变量名时,输入按空白符拆分后依次赋值,最后一个变量会接收该行剩余的全部内容。
常用方式速查
下面的列表给出了 read 命令的常用方式,均可在交互式终端或脚本中直接使用:
read 1987name
从标准输入读取输入并赋值给变量1987name。
read first last
从标准输入读取输入到第一个空格或者回车,将输入的第一个单词放到变量first中,并将该行其他的输入放在变量last中。
read
从标准输入读取一行并赋值给特定变量REPLY。
read -a arrayname
把单词清单读入arrayname的数组里。
read -p "text"
打印提示(text),等待输入,并将输入存储在REPLY中。
read -r line
允许输入包含反斜杠。
read -t 3
指定读取等待时间为3秒。
read -n 2 var
从输入中读取两个字符并存入变量var,不需要按回车读取。
read -d ":" var
用定界符":"结束输入行。
实战示例
读取单个变量
从标准输入读取输入并赋值给变量 1987name:
# read 1987name # 等待读取输入,直到回车后表示输入完毕,并将输入赋值给变量answer
HelloWorld # 控制台输入 HelloWorld
# echo $1987name # 打印变量
HelloWorld
一次读取多个变量
等待一组输入,每个单词之间使用空格隔开,直到回车结束,并分别将单词依次赋值给这三个读入变量:
# read one two three
1 2 3 # 在控制台输入 1 2 3,它们之间用空格隔开
# echo "one = $one, two = $two, three = $three"
one = 1, two = 2, three = 3
这里体现了 read 的关键行为:第一个空格前的单词进 one,第二个空格前的单词进 two,该行剩余内容(这里是 3)全部进 three。
REPLY 内置变量示例
# read # 等待控制台输入,并将结果赋值给特定内置变量REPLY
This is REPLY # 在控制台输入该行
# echo $REPLY # 打印输出特定内置变量REPLY,以确认是否被正确赋值
This is REPLY
当 read 后面不跟任何变量名时,整行输入原样存入 REPLY,适合只需要"取一整行"而无需拆分的场景。
-p 提示符示例
# read -p "Enter your name: " # 输出文本提示,同时等待输入,并将结果赋值给REPLY
Enter you name: stephen # 在提示文本之后输入 stephen
# echo $REPLY
stephen
-p 让提示与读取合二为一,避免了"先 echo 提示、再 read 输入"的两步写法。
-a 数组读取示例
等待控制台输入,并将输入信息视为数组,赋值给数组变量 friends,输入信息用空格隔开数组的每个元素:
# read -a friends
Tim Tom Helen
# echo "They are ${friends[0]}, ${friends[1]} and ${friends[2]}."
They are Tim, Tom and Helen.
注意访问数组元素时要使用 ${数组名[下标]} 的形式,下标从 0 开始。
终端输入密码不回显
补充一个终端输入密码时,不让密码显示出来的例子。
方法 1:使用 -s 选项
#!/bin/bash
read -p "输入密码:" -s pwd
echo
echo password read, is "$pwd"
-s 让输入内容不回显在终端上,配合 -p 即可在一条命令内完成"提示 + 隐藏输入";由于不回显,输入换行后需要手动 echo 补一个空行,避免后续输出紧贴在输入行上。
方法 2:使用 stty 控制终端回显
#!/bin/bash
stty -echo
read -p "输入密码:" pwd
stty echo
echo
echo 输入完毕。
其中,选项 -echo 禁止将输出发送到终端,而选项 echo 则允许发送输出。这种方法通过 stty 直接控制终端回显属性,读取完成后必须用 stty echo 恢复,否则后续命令的所有输出都会"看不见"。
多变量读取并输出
使用 read 命令从键盘读取变量值,并且将值赋给指定的变量,输入如下命令:
read v1 v3 # 读取变量值
执行上面的指令以后,要求键入两个数据,如下所示:
Linux c+ # 输入数据
完成之后,可以使用 echo 命令将指定的变量值输出查看,输入如下命令:
echo $v1 $v3 # 输出变量的值
执行输出变量值的命令以后,将显示用户所输入的数据值,如下所示:
Linux c+ # 输出变量值
注意:使用 echo 命令输出变量值时,必须在变量名前添加符号 $。否则,echo 将直接输出变量名。
与 echo 配合的输出规范
read 读入、echo 输出是交互脚本中最常见的一对组合。关于 echo 的更多转义、换行行为,可以查阅仓库中的 command/echo.md,其同样收录于本仓库的 Linux 命令手册体系内。
仓库中的定位与构建佐证
本手册所在的 command/read.md 是 linux-command 仓库 command 目录下 600 多个 Linux 命令文档之一,command 目录中的每一个 Markdown 文件都是一份独立的命令手册,可直接用于检索、学习或被程序化消费。
从仓库的构建脚本 scripts/build.mjs 可以确认这套文档的完整数据链路:
readMarkdownPaths(scripts/build.mjs)扫描command目录下所有.md文件;createDataJSON(scripts/build.mjs)解析每个文档首部的标题(如read)与描述行,生成命令名称、命令路径和命令描述三项 JSON 索引数据;createTmpToHTML配合 EJS 模板 template/details.ejs 将 Markdown 渲染为可搜索的静态 HTML 详情页。
也就是说,本文讲解的 read 手册既可以通过 README.md 中描述的 Web 版站点搜索查阅,也可以直接阅读 command/read.md 源文件,甚至通过 npm 包按命令名取用对应的 Markdown 文本,例如在 Node.js 中加载 linux-command/command/read.md 得到本文的原始内容。
小结
read 命令的实用价值体现在三个层次:单变量读取满足最基本的交互需求;多变量拆分省去了手工解析输入字符串的麻烦;而 -p、-t、-n、-d、-a、-s、-r 等选项的组合则覆盖了提示输入、超时控制、定长读取、自定义定界符、数组接收、密码隐藏、保留反斜杠等几乎全部脚本交互场景。掌握这些用法,就能写出健壮且友好的 Shell 交互程序。