shell - 变量引用, 用户输入, 超时, 文本读写

# 变量和变量的引用方式

Shell 的变量以 var= 的方式定义,以 $var 或者 ${var} 的方式使用。Shell 的变量没有类型的分别,实际就是一个字符串。因此 Shell 变量的使用和字符串密不可分。这一节先介绍一下变量的一些特殊的引用方法。

1
2
3
4
5
6
7
8
9
$var/${var} - 最基本的用法,返回变量 var 的值——一个字符串。
${var-"something"}   -  var 没有被预先定义时,返回 "something"
${var-"something"} -  var 没有被预先定义,或者被定义为空时,返回 "something"
${var="something"}   -  var 没有被预先定义时,返回 "something",同时设置 var="something"
${var:="something"}  -  var 没有被预先定义,或者被定义为空时,返回 "something",同时设置 var="something"
${var?"something"}   -  var 没有被预先定义时,返回 "something",而后终止脚本。
${var:?"something"}  -  var 没有被预先定义,或者被定义为空时,返回 "something",而后终止脚本。
${var+"something"}   -  var 已经被定义时,返回 "something"
${var:+"something"}  -  var 已经被定义并且不为空时,返回 "something"
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
示例
$ echo ${var}

$ echo ${#var}  # return the length of ${var}
0
$ echo ${var-"hello"}
hello
$ echo ${var}

$ var=""
$ echo ${var-"hello"}

$ echo ${var:-"hello"}
hello
$ echo ${var}

$ echo ${#var}
0
$ unset var
$ echo ${var="hello"}
hello
$ echo ${var}
hello
$ unset var; var=""
$ echo ${var:="hello"}
hello
$ echo ${#var}
5

# 圆括号的使用

除了花括号之外,$ 符号还可以搭配圆括号使用。基本有两种用法:

  • $(command) - 返回 command 执行完毕的输出结果,相当于 command
  • $((expression)) - 执行算术运算 expression 并返回运算结果,例如 $((2 + 3 * 2)) 返回 8。

# 按长度截取字符串

当 Shell 变量中保存着内容时,我们就可以按索引和长度截取字符串中的内容。Shell 变量的索引从 0 开始。主要有两种方式:

  • ${var:pos} - 返回从 pos 开始一直到末尾的字符串。
  • ${var:pos:len} - 返回从 pos 开始长度为 len 的字符串。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
示例
$ var="hello"
$ echo ${var}
hello
$ echo ${#var}
5
$ echo ${var:3}
lo
$ echo ${var:6}

$ echo ${var:0:3}
hel
$ echo ${var:0:6}
hello

# 按匹配截取字符串

Shell 的变量支持从左或者从右删除包含通配符的子串:

  • 使用 # 或者 ## 从左删除子串;
  • 使用 % 或者 %% 从右删除子串。
  • 单符号的版本(#/%)尽可能短地匹配子串;双符号的版本(##/%%)尽可能长地匹配子串。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
示例
$ var="hellohello"
$ echo ${var}
hellohello
$ echo ${var#*ll}
ohello
$ echo ${var##*ll}
o
$ echo ${var%ll*}
hellohe
$ echo ${var%%ll*}
he

# 字符串替换

Shell 的变量也支持字符串替换。

  • ${var/FROM/TO} - 将 $var 中的第一个 FROM 匹配的子串替换成 TO,然后返回。
  • ${var//FROM/TO} - 将 $var 中所有的 FROM 匹配的子串替换成 TO,然后返回。
  • ${var/#FROM/TO} - 若 $var 从第一个字符开始能够匹配 FROM,则替换成 TO 然后返回;否则直接返回 ${var}。
  • ${var/%FROM/TO} - 若 $var 从最后一个字符开始能够匹配 FROM,则替换成 TO 然后返回;否则直接返回 ${var}。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
示例
$ var="hellohello"
$ echo ${var}
hellohello
$ echo ${var/ll/xx}
hexxohello
$ echo ${var//ll/xx}
hexxohexxo
$ echo ${var/#*ll/xx}
xxo
$ echo ${var/#*lx/xx}
hellohello
$ echo ${var/%ll*/xx}
hexx
$ echo ${var/%lx*/xx}
hellohello
$ echo ${var}
hellohello

# 获得用户输入read

# 1.基本读入

read接受用户从键盘的输入:

1
2
3
4
#!/bin/bash
echo -n "Enter your name:"       #-n选项移调末尾换行符,不换行
read name
echo "Hello $name"
1
2
3
输出结果
Enter your name: caishu
Hello caishu
1
2
3
4
5
read的-p选项,直接置顶参数:

read -p "Enter your name:" name 
echo "Hello $name"
read命令会为每个提示符分配变量,若提示符用完了,则将剩下的所有变量,分配给最后一个提示符。

若在read命中不指定变量,read命令会将它收到的任何数据都放进特殊环境变量REPLY中,

1
2
3
4
5
6
7
$read -p "Enter your para:" para1 para2 para3; echo "your parameter is $para1,$para2,$para3..."
Enter your para:1 2 3 4 5 6 7
your parameter is 1,2,34567...

$read -p "Enter your para:" ; echo "your parameter is $REPLY"
Enter your para:caishu
your parameter is caishu

# 2.超时 和 计数

1
2
3
4
5
6
-t:使用read命令时,会一直等用户输入,可以用-t选项来制定计时器,当计时器过期后,read命令会返回一个非零退出状态码。
read -t 5 -p "Please enter your name: " name   #会等5s,可以改变数字以改变等的时间

-n和数字:对输入的字符计数,当输入的字符达到预设的字符数时,它会自动退出,将输入的数据赋给变量。

read -n1 -p "Please enter your name: " name       #只接受一个字符,空格也是字符。

# 3.隐藏方式读取

-s 阻止用户的输入显示在显示器上,(实际上,数据会被显示,只是read命令将文本颜色设置成跟背景颜色一样)

# 4.从文件中读取

read line 会从文本中读取一行,用cat命令的输出通过管道传给含有read的while命令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
#!/bin/bash
#read data from a file

count=1
cat filename | while read line
do 
  echo "Line $count: $line
  count=$[ $count + 1 ]
done
echo "Finished processing the file"
Licensed under CC BY-NC-SA 4.0