From a360d053a63b55e79cba0228241a1f6f535ad3ad Mon Sep 17 00:00:00 2001 From: ruanyf Date: Mon, 16 Mar 2020 20:24:39 +0800 Subject: [PATCH] docs: edit loop --- docs/array.md | 33 ++++++++++++++++++++++++++++++++- docs/condition.md | 25 +++++++++++++++++++++++-- docs/expansion.md | 2 +- docs/loop.md | 40 ++++++++++++++++++++++++---------------- docs/script.md | 8 ++++++++ 5 files changed, 88 insertions(+), 20 deletions(-) diff --git a/docs/array.md b/docs/array.md index a5d3ed8..86d0555 100644 --- a/docs/array.md +++ b/docs/array.md @@ -146,6 +146,16 @@ $ echo ${#a[@]} 上面例子中,把字符串赋值给`100`位置的数组元素,这时的数组只有一个元素。 +注意,如果把上面例子的`*`或`@`,写成具体的下标,就变成返回字符串的长度。 + +```bash +$ a[100]=foo +$ echo ${#a[100]} +3 +``` + +上面例子中,`${#a[100]}`实际上是返回变量`a[100]`的值`foo`的长度。 + `${!array[@]}`或`${!array[*]}`,可以返回数组的哪些位置是有值的。 ```bash @@ -188,11 +198,32 @@ a b d e f ```bash $ foo=(a b c d e f) -$ foo= +$ foo[1]='' +$ echo ${foo[@]} +a c d e f +``` + +上面例子中,将数组的第二个成员设为空字符串,就删除了这个成员。 + +由于空字符串等于空值,所以下面这样写也可以,但是不推荐这种写法。 + +```bash +$ foo[1]= +``` + +上面的写法也相当于删除了数组的第二个成员。 + +如果不写下标,只写数组名,就相当于引用数组的第一个成员。 + +```bash +$ foo=(a b c d e f) +$ foo='' $ echo ${foo[@]} b c d e f ``` +上面的写法相当于删除了数组的第一个成员。 + `unset ArrayName`可以清空整个数组。 ```bash diff --git a/docs/condition.md b/docs/condition.md index 523eee8..1517d53 100644 --- a/docs/condition.md +++ b/docs/condition.md @@ -412,10 +412,10 @@ $ [ -d temp ] || mkdir temp 上面的命令会测试目录`temp`是否存在,如果不存在,就会执行第二个命令,创建这个目录。这种写法非常有助于在脚本中处理错误。 ```bash -[ -d temp ] || exit 1 +[ ! -d temp ] && exit 1 ``` -上面的命令中,如果`temp`目录不存在,脚本会终止,并且返回值为`1`。 +上面的命令中,如果`temp`子目录不存在,脚本会终止,并且返回值为`1`。 `if`结构也可以直接使用上面的控制操作符。 @@ -433,6 +433,27 @@ fi 上面的例子只有在指定文件里面,同时存在搜索词`word1`和`word2`,就会执行`if`的命令部分。 +```bash +[[ -d "$dir_name" ]] && cd "$dir_name" && rm * + +# 等同于 + +if [[ ! -d "$dir_name" ]]; then + echo "No such directory: '$dir_name'" >&2 + exit 1 +fi +if ! cd "$dir_name"; then + echo "Cannot cd to '$dir_name'" >&2 + exit 1 +fi +if ! rm *; then + echo "File deletion failed. Check results" >&2 + exit 1 +fi +``` + +上面例子中,将一个控制操作符号的语句,改写成`if`结构。 + ## case 结构 `case`结构用于表达式有多个值时的判断,可以为每个值指定对应的命令。它类似于包含多个`elif`的`if`结构,但是语义更好。它的语法如下。 diff --git a/docs/expansion.md b/docs/expansion.md index 6a2cb75..81c160e 100644 --- a/docs/expansion.md +++ b/docs/expansion.md @@ -358,7 +358,7 @@ $ echo ${SHELL} /bin/bash ``` -`${!...}`可以返回所有匹配的变量名。 +`${!...*}`或`${!...@}`可以返回所有匹配的变量名。 ```bash $ echo ${!S*} diff --git a/docs/loop.md b/docs/loop.md index 422dbb7..aa37db9 100644 --- a/docs/loop.md +++ b/docs/loop.md @@ -14,7 +14,19 @@ done 上面代码中,只要满足条件`condition`,就会执行命令`statements`。然后,再次判断是否满足条件`condition`,只要满足,就会一直执行下去。只有不满足条件,才会退出循环。 -判断条件`condition`可以使用`test`命令,跟`if`语句的判断一致。 +循环条件`condition`可以使用`test`命令,跟`if`语句的判断条件一致。 + +```bash +#!/bin/bash + +number=0 +while [ "$number" -lt 10 ]; do + echo "Number = $number" + number=$((number + 1)) +done +``` + +上面例子中,只要变量`number`小于10,就会不断加1,直到`number`等于10,然后退出循环。 关键字`do`可以跟`while`不在同一行,这时两者之间不需要使用分号分隔。 @@ -33,20 +45,6 @@ done $ while true; do echo 'Hi, while looping ...'; done ``` -下面是另一个例子 - -```bash -#!/bin/bash - -number=0 -while [ "$number" -lt 10 ]; do - echo "Number = $number" - number=$((number + 1)) -done -``` - -上面例子中,只要变量`number`小于10,就会不断加1,直到`number`等于10,然后退出循环。 - `while`的条件部分也可以是执行一个命令。 ```bash @@ -65,7 +63,11 @@ $ while true; false; do echo 'Hi, looping ...'; done ## break,continue -Bash 提供了两个内部命令,用来在循环内部控制程序流程。`break`命令立即终止一个循环,且程序继续执行循环之后的语句。`continue`命令导致程序跳过循环中剩余的语句,且程序继续执行下一次循环。 +Bash 提供了两个内部命令,用来在循环内部跳出循环。 + +`break`命令立即终止循环,程序继续执行循环之后的语句,即不再执行剩下的循环。 + +`continue`命令立即终止本轮循环,开始执行下一轮循环。 ## until 循环 @@ -194,6 +196,12 @@ done `in list`的部分可以省略,这时`list`默认等于脚本的所有参数`$@`。但是,为了可读性,最好还是不要省略,参考下面的例子。 ```bash +for filename; do + echo "$filename" +done + +# 等同于 + for filename in "$@" ; do echo "$filename" done diff --git a/docs/script.md b/docs/script.md index 0496025..46f0ed7 100644 --- a/docs/script.md +++ b/docs/script.md @@ -195,6 +195,14 @@ done 上面例子中,`$@`返回一个全部参数的列表,然后使用`for`循环遍历。 +如果多个参数放在双引号里面,视为一个参数。 + +```bash +$ script.sh "a b" +``` + +上面例子中,Bash 会认为`"a b"`是一个参数,`$1`会返回`a b`。注意,返回时不包括双引号。 + ## shift 命令 `shift`命令可以改变脚本参数,每次执行都会移除脚本当前的第一个参数(`$1`),使得后面的参数向前一位,即`$2`变成`$1`、`$3`变成`$2`、`$4`变成`$3`,以此类推。