Skip to content

Commit d5b9990

Browse files
committed
docs: edit script/read
1 parent 6b05c0c commit d5b9990

4 files changed

Lines changed: 128 additions & 34 deletions

File tree

docs/condition.md

Lines changed: 8 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ test expression
107107

108108
上面的`expression`是一个表达式,其执行结果是`true`或者是`false`。当表达式为真时,这个`test`命令的返回值为`0`,当表达式为假时,`test`命令的返回值为`1`
109109

110-
注意,第二种和第三种写法,`[``]`与内部的表达式之间都必须有空格。写法三比前两种写法多出一个功能,就是支持正则判断,详见后文。
110+
注意,第二种和第三种写法,`[``]`与内部的表达式之间都必须有空格。写法三比前两种写法多出一个功能,就是支持正则判断,其他完全一样,详见后文。
111111

112112
下面是三种写法的例子,判断一个文件是否存在。
113113

@@ -190,7 +190,7 @@ fi
190190
exit
191191
```
192192

193-
上面代码中,`$FILE`放在双引号之中。这样可以防止`$FILE`为空的错误,因为只要放在双引号之中,返回的就总是一个字符串。另外,叫不最后的`exit`命令,可以保证如果没有出错,退出状态总是为0。
193+
上面代码中,`$FILE`放在双引号之中。这样可以防止`$FILE`为空的错误,因为只要放在双引号之中,返回的就总是一个字符串。另外,最后的`exit`命令,可以保证如果没有出错,退出状态总是为0。
194194

195195
### 字符串表达式
196196

@@ -228,7 +228,7 @@ else
228228
fi
229229
```
230230

231-
上面代码中,我们首先确定`$ANSWER`字符串是否为空。如果为空,我们就终止脚本,并把退出状态设为零。注意这个应用于echo 命令的重定向操作。其把错误信息 “There is no answer.重定向到标准错误,这是处理错误信息的“合理”方法。如果字符串不为空,我们就计算 字符串的值,看看它是否等于“yes,” “no,” 或者“maybe”。为此使用了 elif,它是 “else if” 的简写。 通过使用 elif,我们能够构建更复杂的逻辑测试
231+
上面代码中,首先确定`$ANSWER`字符串是否为空。如果为空,就终止脚本,并把退出状态设为`1`。注意,这里的`echo`命令把错误信息`There is no answer.`重定向到标准错误,这是处理错误信息的常用方法。如果`$ANSWER`字符串不为空,就判断它的值是否等于`yes``no`或者`maybe`
232232

233233
注意,字符串判断时,变量要放在双引号之中,比如`[ -n "$COUNT" ]`,否则变量替换成字符串以后,`test`命令可能会报错,提示参数过多。另外,如果不放在双引号之中,变量为空时,命令会变成`[ -n ]`,这时会判断为真。如果放在双引号之中,`[ -n "" ]`就判断为伪。
234234

@@ -269,7 +269,7 @@ else
269269
fi
270270
```
271271

272-
这个脚本中有趣的地方是怎样来确定一个整数是偶数还是奇数。通过用模数2对数字执行求模操作, 就是用数字来除以2,并返回余数,从而知道数字是偶数还是奇数
272+
上面例子中,通过求余数,判断一个数字是偶数还是奇数
273273

274274
### 正则表达式
275275

@@ -286,30 +286,16 @@ fi
286286
# test-integer2: evaluate the value of an integer.
287287
INT=-5
288288
if [[ "$INT" =~ ^-?[0-9]+$ ]]; then
289-
if [ $INT -eq 0 ]; then
290-
echo "INT is zero."
291-
else
292-
if [ $INT -lt 0 ]; then
293-
echo "INT is negative."
294-
else
295-
echo "INT is positive."
296-
fi
297-
if [ $((INT % 2)) -eq 0 ]; then
298-
echo "INT is even."
299-
else
300-
echo "INT is odd."
301-
fi
302-
fi
289+
echo "INT is an integer."
290+
exit 0
303291
else
304-
echo "INT is not an integer." >&2
305-
exit 1
292+
echo "INT is not an integer." >&2
293+
exit 1
306294
fi
307295
```
308296

309297
上面代码中,先判断一个变量是否为正数或负数,如果是的话,再进行进一步判断。
310298

311-
除了支持正则表达式,`[[ ... ]]``[ ... ]`完全一样。
312-
313299
### 算术条件
314300

315301
Bash 还提供了`((...))`作为算术条件。如果算术计算的结果是非零值,则表示判断成立。

docs/function.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ $ log_msg "This is sample log message"
128128

129129
## 返回值
130130

131-
`return`命令用于从函数返回一个值。
131+
`return`命令用于从函数返回一个值。函数执行到这条命令,就不再往下执行了,直接返回了。
132132

133133
```bash
134134
function func_return_value {
@@ -144,6 +144,15 @@ $ echo "Value returned by function is: $?"
144144
Value returned by function is: 10
145145
```
146146

147+
`return`后面不跟参数,只用于返回也是可以的。
148+
149+
```bash
150+
function name {
151+
commands
152+
return
153+
}
154+
```
155+
147156
## 全局变量和局部变量
148157

149158
Bash 函数体内直接声明的变量,属于全局变量,整个脚本都可以读取。这一点需要特别小心。

docs/quotation.md

Lines changed: 53 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,21 +167,19 @@ $ echo "$(cal)"
167167
168168
上面命令中,如果`$(cal)`不放在双引号之中,`echo`就会将所有结果以单行输出,丢弃了所有原始的格式。
169169
170-
## Here 字符串
170+
## Here 文档
171171
172-
Here 字符串是一种输入多行字符串的方法,格式如下。
172+
Here 文档(here document)是一种输入多行字符串的方法,格式如下。
173173
174174
```bash
175175
<< token
176176
text
177177
token
178178
```
179179
180-
它的格式分成开始标记(`<< token`)和结束标记(`token`)。开始标记是两个小于号 + Here 字符串的名称,名称可以随意取;结束标记是单独一行的 Here 字符串名称。两者之间就是多行字符串的内容。
181-
182-
```bash
180+
它的格式分成开始标记(`<< token`)和结束标记(`token`)。开始标记是两个小于号 + Here 文档的名称,名称可以随意取;结束标记是单独一行的 Here 文档名称。两者之间就是多行字符串的内容。
183181
184-
下面是一个输出 HTML 代码的例子。
182+
下面是一个通过 Here 文档输出 HTML 代码的例子。
185183
186184
```bash
187185
$ cat << _EOF_
@@ -199,11 +197,11 @@ $ cat << _EOF_
199197
_EOF_
200198
```
201199
202-
Here 字符串内部会发生变量替换,但是双引号和单引号都失去语法作用,变成了普通字符。
200+
Here 文档内部会发生变量替换和通配符扩展,但是双引号和单引号都失去语法作用,变成了普通字符。
203201
204202
```bash
205203
$ foo='hello world'
206-
$ echo << _example_
204+
$ cat << _example_
207205
$foo
208206
"$foo"
209207
'$foo'
@@ -216,14 +214,58 @@ hello world
216214
217215
上面例子中,变量`$foo`发生了替换,但是双引号和单引号都原样输出了,表明它们已经失去了引用的功能。
218216
219-
Here 字符串的本质是重定向,它将字符串重定向输出给某个命令,相当于包含了`echo`命令。所以,Here 字符串只适合那些可以接受标准输入作为参数的命令,对于其他命令无效,比如`echo`命令就不能用 Here 字符串。
217+
如果不希望发生变量替换和通配符扩展,可以把 Here 文档的开始标记放在单引号之中。
218+
219+
```bash
220+
$ foo='hello world'
221+
$ cat << '_example_'
222+
$foo
223+
"$foo"
224+
'$foo'
225+
_example_
226+
227+
$foo
228+
"$foo"
229+
'$foo'
230+
```
231+
232+
上面例子中,Here 文档的开始标记(`_example_`)放在单引号之中,导致变量替换失效了。
233+
234+
Here 文档的本质是重定向,它将字符串重定向输出给某个命令,相当于包含了`echo`命令。所以,Here 字符串只适合那些可以接受标准输入作为参数的命令,对于其他命令无效,比如`echo`命令就不能用 Here 文档。
220235
221236
```bash
222237
$ echo << _example_
223238
hello
224239
_example_
225240
```
226241
227-
上面例子不会有任何输出,因为 Here 字符串对于`echo`命令无效。
242+
上面例子不会有任何输出,因为 Here 文档对于`echo`命令无效。
243+
244+
此外,Here 文档也不能作为变量的值,只能用于命令的参数。
245+
246+
## Here 字符串
247+
248+
Here 文档还有一个变体,叫做 Here 字符串(Here string),使用三个小于号(`<<<`)表示。
249+
250+
```bash
251+
<<< string
252+
```
253+
254+
它的作用是将字符串通过标准输入,传递给命令。
255+
256+
```bash
257+
$ md5sum <<< 'ddd'
258+
# 等同于
259+
$ echo 'ddd' | md5sum
260+
```
261+
262+
有些命令直接接受给定的参数,与通过标准输入接受参数,结果是不一样的。所以才有了这个语法,使得将字符串通过标准输入传递给命令更方便,比如`cat`命令只接受标准输入传入的字符串。
263+
264+
```bash
265+
$ cat <<< 'hi there'
266+
# 等同于
267+
$ echo 'hi there' | cat
268+
```
269+
270+
上面的第一种语法使用了 Here 字符串,要比第二种语法看上去语义更好,也更简洁。
228271
229-
此外,Here 字符串也不能作为变量的值,只能用于命令的参数。

docs/script.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ Enter one or more values > a b c d
407407
REPLY = 'a b c d'
408408
```
409409

410+
`read`命令除了读取键盘输入,可以用来读取文件,详见下一节的例子。
411+
410412
`read`命令的参数如下。
411413

412414
**(1)-t 参数**
@@ -470,6 +472,61 @@ abc
470472
- `-s`:使得用户的输入不显示在屏幕上,这常常用于输入密码或保密信息。
471473
- `-u fd`:使用文件描述符`fd`作为输入。
472474

475+
## IFS 变量
476+
477+
`read`命令读取的值,默认是以空格分隔。可以通过自定义环境变量`IFS`(内部字段分隔符,Internal Field Separator 的缩写),修改分隔标志。
478+
479+
`IFS`的默认值是空格、Tab 符号、换行符号,通常取第一个(即空格)。
480+
481+
如果把`IFS`定义成冒号(`:`)或分号(`;`),就可以分隔以这两个符号分隔的值,这对读取文件很有用。
482+
483+
```bash
484+
#!/bin/bash
485+
# read-ifs: read fields from a file
486+
487+
FILE=/etc/passwd
488+
489+
read -p "Enter a username > " user_name
490+
file_info="$(grep "^$user_name:" $FILE)"
491+
492+
if [ -n "$file_info" ]; then
493+
IFS=":" read user pw uid gid name home shell <<< "$file_info"
494+
echo "User = '$user'"
495+
echo "UID = '$uid'"
496+
echo "GID = '$gid'"
497+
echo "Full Name = '$name'"
498+
echo "Home Dir. = '$home'"
499+
echo "Shell = '$shell'"
500+
else
501+
echo "No such user '$user_name'" >&2
502+
exit 1
503+
fi
504+
```
505+
506+
上面例子中,`IFS`设为冒号,然后用来分解`/etc/passwd`文件的一行。`IFS`的赋值命令和`read`命令写在一行,这样的话,`IFS`的改变仅对后面的命令生效,该命令执行后`IFS`会自动恢复原来的值。如果不写在一行,就要采用下面的写法。
507+
508+
```bash
509+
OLD_IFS="$IFS"
510+
IFS=":"
511+
read user pw uid gid name home shell <<< "$file_info"
512+
IFS="$OLD_IFS"
513+
```
514+
515+
另外,上面例子中,`<<<`是 Here 字符串,用于将变量值转为标准输入,因为`read`命令只能解析标准输入。
516+
517+
如果`IFS`设为空字符串,就可以读取一行。
518+
519+
```bash
520+
#!/bin/bash
521+
input="/path/to/txt/file"
522+
while IFS= read -r line
523+
do
524+
echo "$line"
525+
done < "$input"
526+
```
527+
528+
上面的命令可以逐行读取文件,每一行存入变量`line`,打印出来以后再读取下一行。
529+
473530
## 命令执行结果
474531

475532
命令执行结束后,会有一个返回值。`0`表示执行成功,非`0`(通常是`1`)表示执行失败。环境变量`$?`可以读取前一个命令的返回值。

0 commit comments

Comments
 (0)