Skip to content

Commit d2945f4

Browse files
committed
docs: add read.md
1 parent bd06384 commit d2945f4

File tree

3 files changed

+250
-236
lines changed

3 files changed

+250
-236
lines changed

chapters.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
- string.md: 字符串操作
77
- arithmetic.md: 算术运算
88
- script.md: 脚本入门
9+
- read.md: read 命令
910
- condition.md: 条件判断
1011
- loop.md: 循环
1112
- function.md: 函数

docs/read.md

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
# read 命令
2+
3+
## 用法
4+
5+
有时,脚本需要用户输入参数,这时可以使用`read`命令。它将用户的输入存入一个变量,方便后面的代码使用。用户按下回车键,就表示输入结束。
6+
7+
`read`命令的格式如下。
8+
9+
```bash
10+
read [-options] [variable...]
11+
```
12+
13+
上面语法中,`options`是参数选项,`variable`是用来保存输入数值的一个或多个变量名。如果没有提供变量名,环境变量`REPLY`会包含用户输入的一整行数据。
14+
15+
下面是一个例子`demo.sh`
16+
17+
```bash
18+
#!/bin/bash
19+
20+
echo -n "输入一些文本 > "
21+
read text
22+
echo "你的输入:$text"
23+
```
24+
25+
上面例子中,先显示一行提示文本,然后会等待用户输入文本。用户输入的文本,存入变量`text`,在下一行显示出来。
26+
27+
```bash
28+
$ bash demo.sh
29+
输入一些文本 > 你好,世界
30+
你的输入:你好,世界
31+
```
32+
33+
`read`可以接受用户输入的多个值。
34+
35+
```bash
36+
#!/bin/bash
37+
echo Please, enter your firstname and lastname
38+
read FN LN
39+
echo "Hi! $LN, $FN !"
40+
```
41+
42+
上面例子中,`read`根据用户的输入,同时为两个变量赋值。
43+
44+
如果用户的输入项少于`read`命令给出的变量数目,那么额外的变量值为空。如果用户的输入项多于定义的变量,那么多余的输入项会包含到最后一个变量中。
45+
46+
如果`read`命令之后没有定义变量名,那么环境变量`REPLY`会包含所有的输入。
47+
48+
```bash
49+
#!/bin/bash
50+
# read-single: read multiple values into default variable
51+
echo -n "Enter one or more values > "
52+
read
53+
echo "REPLY = '$REPLY'"
54+
```
55+
56+
上面脚本的运行结果如下。
57+
58+
```bash
59+
$ read-single
60+
Enter one or more values > a b c d
61+
REPLY = 'a b c d'
62+
```
63+
64+
`read`命令除了读取键盘输入,可以用来读取文件。
65+
66+
```bash
67+
while read myline
68+
do
69+
echo "$myline"
70+
done < $filename
71+
```
72+
73+
上面的例子通过`read`命令,读取一个文件的内容。`done`命令后面的定向符`<`,将文件导向`read`命令,每次读取一行,存入变量`myline`,直到文件读取完毕。
74+
75+
## 参数
76+
77+
`read`命令的参数如下。
78+
79+
**(1)-t 参数**
80+
81+
`read`命令的`-t`参数,设置了超时的秒数。如果超过了指定时间,用户仍然没有输入,脚本将放弃等待,继续向下执行。
82+
83+
```bash
84+
#!/bin/bash
85+
86+
echo -n "输入一些文本 > "
87+
if read -t 3 response; then
88+
echo "用户已经输入了"
89+
else
90+
echo "用户没有输入"
91+
fi
92+
```
93+
94+
上面例子中,输入命令会等待3秒,如果用户超过这个时间没有输入,这个命令就会执行失败。`if`根据命令的返回值,转入`else`代码块,继续往下执行。
95+
96+
环境变量`TMOUT`也可以起到同样作用,指定`read`命令等待用户输入的时间(单位为秒)。
97+
98+
```bash
99+
$ TMOUT=3
100+
$ read response
101+
```
102+
103+
上面例子也是等待3秒,如果用户还没有输入,就会超时。
104+
105+
**(2)-p 参数**
106+
107+
`-p`参数指定用户输入的提示信息。
108+
109+
```bash
110+
read -p "Enter one or more values > "
111+
echo "REPLY = '$REPLY'"
112+
```
113+
114+
上面例子中,先显示`Enter one or more values >`,再接受用户的输入。
115+
116+
**(3)-a 参数**
117+
118+
`-a`参数把用户的输入赋值给一个数组,从零号位置开始。
119+
120+
```bash
121+
$ read -a people
122+
alice duchess dodo
123+
$ echo ${people[2]}
124+
dodo
125+
```
126+
127+
上面例子中,用户输入被赋值给一个数组`people`,这个数组的2号成员就是`dodo`
128+
129+
**(4)-n 参数**
130+
131+
`-n`参数指定只读取若干个字符作为变量值,而不是整行读取。
132+
133+
```bash
134+
$ read -n 3 letter
135+
abcdefghij
136+
$ echo $letter
137+
abc
138+
```
139+
140+
上面例子中,变量`letter`只包含3个字母。
141+
142+
**(5)其他参数**
143+
144+
- `-d delimiter`:定义字符串`delimiter`的第一个字符作为用户输入的结束,而不是一个换行符。
145+
- `-r`:raw 模式,表示不把用户输入的反斜杠字符解释为转义字符。
146+
- `-s`:使得用户的输入不显示在屏幕上,这常常用于输入密码或保密信息。
147+
- `-u fd`:使用文件描述符`fd`作为输入。
148+
149+
## IFS 变量
150+
151+
`read`命令读取的值,默认是以空格分隔。可以通过自定义环境变量`IFS`(内部字段分隔符,Internal Field Separator 的缩写),修改分隔标志。
152+
153+
`IFS`的默认值是空格、Tab 符号、换行符号,通常取第一个(即空格)。
154+
155+
如果把`IFS`定义成冒号(`:`)或分号(`;`),就可以分隔以这两个符号分隔的值,这对读取文件很有用。
156+
157+
```bash
158+
#!/bin/bash
159+
# read-ifs: read fields from a file
160+
161+
FILE=/etc/passwd
162+
163+
read -p "Enter a username > " user_name
164+
file_info="$(grep "^$user_name:" $FILE)"
165+
166+
if [ -n "$file_info" ]; then
167+
IFS=":" read user pw uid gid name home shell <<< "$file_info"
168+
echo "User = '$user'"
169+
echo "UID = '$uid'"
170+
echo "GID = '$gid'"
171+
echo "Full Name = '$name'"
172+
echo "Home Dir. = '$home'"
173+
echo "Shell = '$shell'"
174+
else
175+
echo "No such user '$user_name'" >&2
176+
exit 1
177+
fi
178+
```
179+
180+
上面例子中,`IFS`设为冒号,然后用来分解`/etc/passwd`文件的一行。`IFS`的赋值命令和`read`命令写在一行,这样的话,`IFS`的改变仅对后面的命令生效,该命令执行后`IFS`会自动恢复原来的值。如果不写在一行,就要采用下面的写法。
181+
182+
```bash
183+
OLD_IFS="$IFS"
184+
IFS=":"
185+
read user pw uid gid name home shell <<< "$file_info"
186+
IFS="$OLD_IFS"
187+
```
188+
189+
另外,上面例子中,`<<<`是 Here 字符串,用于将变量值转为标准输入,因为`read`命令只能解析标准输入。
190+
191+
如果`IFS`设为空字符串,就等同于将整行读入一个变量。
192+
193+
```bash
194+
#!/bin/bash
195+
input="/path/to/txt/file"
196+
while IFS= read -r line
197+
do
198+
echo "$line"
199+
done < "$input"
200+
```
201+
202+
上面的命令可以逐行读取文件,每一行存入变量`line`,打印出来以后再读取下一行。
203+

0 commit comments

Comments
 (0)