编程语言的分类
编译型语言:需要使用编译器将其编译生成可执行的文件,
c C++
解释型语言:需要使用解析器区解析语言。
shell脚本语言 python
shell语言使用的解析器
1. bash解析器 ----> ubuntu系统使用的是bash解析器
2. sh解析器 ----> 开发板中启动linux系统时,使用的sh解析器
3. csh
4. ksh
什么是shell
shell翻译成中文:贝壳
shell是用来对linux系统起到保护的作用,通过输入命令,shell解析器解析输入的命令,
根据命令的功能最终实现硬件的控制,并将结果回显到终端之上。
shell脚本文件
-
shell脚本文件的名字一般以.sh结尾.
-
在shell脚本文件中本质上就是很多liunx命令的集合,
并不是简单的将命令在shell脚本文件中罗列,会有一定的代码的逻辑。 -
当执行脚本文件时,脚本文件中的命令会按照逻辑依次执行,并完成一个特定的功能。
第一个shell脚本文件
1. 创建一个脚本文件 --> 01first.sh
2. 打开脚本文件添加以下内容
#!/bin/bash
# 提示使用的bash解析器解析脚本文件
# shell中的单行注释使用“#”
# shell命令,在终端打印“hello world”字符串
# echo : shell命令,类似于C语言中的printf
echo "hello world!"
3. 执行脚本文件
方式1:添加可执行权限,使用"./脚本文件名"执行脚本文件
chmod 0777 01first.sh
./01first.sh
脚本文件必须使用chmod命令添加可执行的权限,
会重新开启一个新的终端执行脚本文件,并将执行的结果返回到当前的终端
方式2:使用bash命令执行脚本文件
bash 01first.sh
脚本文件可以没有可执行的权限,
会重新开启一个新的终端执行脚本文件,并将执行的结果返回到当前的终端
方式3:使用source命令执行脚本文件
source 01first.sh
脚本文件可以没有可执行的权限,
在当前终端执行脚本文件,并将结果返回到当前终端之上
shell中变量的使用
shell中变量的定义
格式:
变量名=初始值
变量名='初始值'
变量名="初始值"
1. 在shell中定义变量时,变量时没有数据类型之分的,都当成字符串处理。
string=helloworld
number=123456789 # 字符串
2. 在shell中定义变量时,等号两边不允许有空格。
var1=hello #OK
var2 = world #Error
3. 如果初始化的值的字符串之间没有空格,使用以上三种定义变量的方式都可以。
var3=helloworld
var4='helloworld'
var5="helloworld" # 初始值之间没有空格,三种方式等价
4. 如果变量初始值的字符串之间有空格,使用''或者""括起来
var6=hello world # Error
var7='hello world' # Ok
var8="hello world" # Ok
5. 如果使用某个变量的值进行赋值,不要使用''括起来。
var9=${var5} # Ok var9=helloworld
var10="${var5}" # OK var10=helloworld 双引号中的变量会被解析
var11='${var5}' # OK, 语法不报错 var11=${var5} 单引号中的变量不会被解析
shell中变量的引用
格式:
${变量名}
或者
$变量名
1. 对于初学者来说,推荐大家使用${变量名}的方式引用变量
var1=hello
var2=world
var3=$var1 # OK
var4=${var2} # OK
var5=${var1}world # OK var5=helloworld
var5=$var1world # OK 语法没有错误,把var1world当成一个变量名,
# 此变量没有定义,就是一个空值
shell变量定义和引用的测试代码:
#!/bin/bash
# your code
echo "1. 在shell中定义变量时,变量时没有数据类型之分的,都当成字符串处理。"
string=helloworld
number=123456789 # 字符串
echo ${string}
echo $number
echo "2. 在shell中定义变量时,等号两边不允许有空格。"
var1=hello #OK
# var2 = world #Error
echo "3. 如果初始化的值的字符串之间没有空格,使用以上三种定义变量的方式都可以。"
var3=helloworld
var4='helloworld'
var5="helloworld" # 初始值之间没有空格,三种方式等价
echo "var3 = ${var3}"
echo "var4 = ${var4}"
echo "var5 = ${var5}"
echo "4. 如果变量初始值的字符串之间有空格,使用''或者\"\"括起来"
# var6=hello world # Error
var7='hello world' # Ok
var8="hello world" # Ok
echo "var6 = ${var6}"
echo "var7 = ${var7}"
echo "var8 = ${var8}"
echo "5. 如果使用某个变量的值进行赋值,不要使用''括起来。"
var9=${var5} # Ok var9=helloworld
var10="${var5}" # OK var10=helloworld 双引号中的变量会被解析
var11='${var5}' # OK, 语法不报错 var11=${var5} 单引号中的变量不会被解析
echo "var9 = ${var9}"
echo "var10 = ${var10}"
echo "var11 = ${var11}"
shell中的位置变量
执行shell脚本文件时,给shell脚本文件传递参数,在shell脚本文件中获取传递的参数,
使用的就是shell中的位置变量。
$0 ---> 执行的脚本文件的名字
$1 ---> 执行脚本文件时传递的第1个参数
$2 ---> 执行脚本文件时传递的第2个参数
.....
$9 ---> 执行脚本文件时传递的第9个参数
$10 ---> 执行脚本文件时传递的第1个参数的值和字符0拼接得到新的字符串
$11 ---> 执行脚本文件时传递的第1个参数的值和字符1拼接得到新的字符串
${10} ---> 执行脚本文件时传递的第10个参数
${11} ---> 执行脚本文件时传递的第11个参数
....
${n} ---> 执行脚本文件时传递的第n个参数,
如果n>=10,此时n使用花括号括起来。
$* ---> 获取所有的参数,不包括执行脚本文件的名字
$@ ---> 获取所有的参数,不包括执行脚本文件的名字
$# ---> 获取执行脚本文件时参数的个数,不包括执行脚本文件的名字
shell中位置变量的测试代码:
#!/bin/bash
# your code
echo '$0 : 表示脚本文件的名字'
echo $0
echo '$1 : 表示执行脚本文件时的第1个参数'
echo $1
echo '$2 : 表示执行脚本文件时的第2个参数'
echo $2
echo '$10 : 表示执行脚本文件时的第1个参数和字符0拼接一个新的字符串'
echo $10
echo '${10} : 表示执行脚本文件时的第10个参数'
echo ${10}
echo '$* : 表示执行脚本文件时传递的所有的参数,不包括脚本文件名'
echo $*
echo '$@ : 表示执行脚本文件时传递的所有的参数,不包括脚本文件名'
echo $@
echo '$# : 表示执行脚本文件时传递的所有的参数个数和,不包括脚本文件名'
echo $#
----------------------------------------------------------------
linux@ubuntu:~/DC22101/day03$ bash 03variable.sh aa bb cc dd ee ff gg hh ii kk
$0 : 表示脚本文件的名字
03variable.sh
$1 : 表示执行脚本文件时的第1个参数
aa
$2 : 表示执行脚本文件时的第2个参数
bb
$10 : 表示执行脚本文件时的第1个参数和字符0拼接一个新的字符串
aa0
${10} : 表示执行脚本文件时的第10个参数
kk
$* : 表示执行脚本文件时传递的所有的参数,不包括脚本文件名
aa bb cc dd ee ff gg hh ii kk
$@ : 表示执行脚本文件时传递的所有的参数,不包括脚本文件名
aa bb cc dd ee ff gg hh ii kk
$# : 表示执行脚本文件时传递的所有的参数个数和,不包括脚本文件名
10
定义shell变量的关键字
1. readonly ---> 定义只读的变量
2. unset ---> 取消变量的定义
3. local ---> 定义局部变量
shell中关键字使用的测试代码:
#!/bin/bash
# your code
# 定义只读变量,定义时必须初始化
readonly var1="helloworld"
echo "var1 = ${var1}"
var1='nihao' # error 只读变量不可以被修改
# 取消变量的定义
var2=helloworld
echo "定义变量 : var2 = ${var2}"
unset var2 # 取消变量的定义,
echo "使用unset取消变量定义:var2 = ${var2}"
# 取消变量定义之后,在使用变量就是一个空值
# 使用local定义局部变量
# 定义一个shell函数
function func()
{
# 在shell的函数中定义的变量默认也是全局的变量
var3="global variable test code"
# 可以使用local在函数中定义一个局部的变量
local var4="local variable test code"
echo "local variable : func::var4 = $var4"
}
# 调用shell中的函数
func
echo "global variable :var3 = $var3"
echo "local variable :var4 = $var4" # 变量var4是局部变量,因此此处是一个空值
----------------------------------------------------
linux@ubuntu:~/shell/day03$ bash 04variable.sh
var1 = helloworld
04variable.sh: line 7: var1: readonly variable
定义变量 : var2 = helloworld
使用unset取消变量定义:var2 =
local variable : func::var4 = local variable test code
global variable :var3 = global variable test code
local variable :var4 =
linux@ubuntu:~/shell/day03$
系统环境变量->PATH
打印PATH环境变量的值
方式1,使用echo $PATH命令打印环境变量的值
linux@ubuntu:~/shell/day03$ echo ${PATH}
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
方式2,使用env命令打印系统环境变量的值
linux@ubuntu:~/shell/day03$ env
SHELL=/bin/bash
PWD=/home/linux/shell/day03
HOME=/home/linux
USERNAME=linux
USER=linux
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
PATH环境变量的作用
PATH环境变量用来指定命令的执行的路径,
当用户在终端输入命令之后,默认从PATH环境变量指定的路径下查找对应的命令,
如果找到对应的命令则执行对应的命令,如果没有找到对应的命令则报命令没有发现的错误。
PATH环境变量指定路径的格式:
PATH=路径1:路径2:路径3:.....
如果自己编写的C语言的程序,运行时需要指定可执行程序的路径"./可执行程序的名字"。
如何实现自己编写的可执行程序通过在终端输入可执行程序的名字也可以运行可执行程序。
方式1:将自己编写的可执行程序拷贝到PATH环境变量指定的路径下
方式2:将自己可执行程序对应的路径添加到PATH环境变量中。
通过终端修改PATH变量的值
在终端执行以下命令
$ export PATH=$PATH:/home/linux/shell/day03
| | | | |----> 指定自己可执行程序的路径,使用绝对路径
| | | |------> 目录的分隔符
| | |----> 将PATH变量之前的值展开
| |----> 给PATH变量赋值
|-----> 导出环境变量
特点:只对当前终端有效,终端一旦重启,配置将无效
修改家目录下的.bashrc文件
1. 打开vi ~/.bashrc文件
2. 将以下内容添加到.bashrc文件的最后边
export PATH=$PATH:/home/linux/shell/day03
|----> 需要修改为自己的路径
3. 使修改的环境变量立即生效
source ~/.bashrc
4. 特点:只对当前用户有效,其他用户无效
修改/etc目录下的bash.bashrc文件
1. 打开sudo vi /etc/bash.bashrc文件
2. 将以下内容添加到/etc/bash.bashrc文件的最后边
export PATH=$PATH:/home/linux/shell/day03
|----> 需要修改为自己的路径
3. 使修改的环境变量立即生效
source /etc/bash.bashrc
4. 特点:对所有的用户有效
修改/etc目录下的profile文件
1. 打开sudo vi /etc/profile文件
2. 将以下内容添加到/etc/profile文件的最后边
export PATH=$PATH:/home/linux/shell/day03
|----> 需要修改为自己的路径
3. 使修改的环境变量立即生效
source /etc/profile
4. 特点:对所有的用户有效
修改/etc目录下的environment文件
1. 打开sudo vi /etc/environment文件
2. 对/etc/environmen中的PATH环境变量的值进行修改,将/home/linux/shell/day03路径
添加到PATH变量中
\|/-----> 添加的自己的路径,路径之间使用:隔开
PATH="/home/linux/shell/day03/:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin"
3. 使修改的环境变量立即生效
source /etc/environment
4. 特点:对所有的用户有效
shell中数组
shell中数组的定义
1. shell中只支持一维数组的定义,不支持多维数组的定义
2. 定义数组的格式
数组名=(初始值0 初始值1 初始值2 初始值3 初始值4 ....)
eg:
num_arr=(11 22 33 44 55 66) # 数组中的成员个数为6,数组的下标从0开始
数组名=([0]=初始值0 [1]=初始值1 [2]=初始值2 ....) # 指定对某个成员初始化
eg:
num_arr=([0]=11 [1]=22 [4]=55 [7]=88) # 数组中成员的个数为4个
num_arr=([0]=11 [1]=22 [2]=33 [3]=44) # 数组中成员的个数为4个
shell中数组的引用
1. 访问数组的某个成员
${数组名[下标]}
2. 修改数组中某个成员的值
数组名[下标]=修改的值
3. 访问数组中所有的成员
${数组名[*]}
${数组名[@]}
4. 统计数组中成员的个数
${#数组名[*]}
${#数组名[@]}
5. 统计数组中某个成员的字符的个数
${#数组名[下标]}
6. 给数组追加成员
数组名[下标]=初始值
#!/bin/bash
# your code
# 1. 定义一个普通的数组
arr1=(11 22 33 44 55 66)
# 访问数组中的某一个成员
echo "arr1[2] = ${arr1[2]}"
# 修改数组中某个成员的值
echo "修改之前:arr1[5] = ${arr1[5]}"
arr1[5]=77
echo "修改之后:arr1[5] = ${arr1[5]}"
# 访问数组中的所有的成员
echo "arr1 = ${arr1[*]}"
echo "arr1 = ${arr1[@]}"
# 统计数组中成员的个数
echo "arr1成员个数 = ${#arr1[*]}"
echo "arr1成员个数 = ${#arr1[@]}"
# 统计数组中某个元素的长度
echo "arr1[1]成员字符个数 = ${#arr1[1]}"
# 给数组追加成员
echo "追加成员之前,arr1成员个数 = ${#arr1[*]}"
arr1[10]=111
echo "追加成员之后,arr1成员个数 = ${#arr1[@]}"
# 2. 定义一个数组,指定数组中的成员初始化
arr2=([0]=aa [1]=bb [3]=dd [7]=hh)
# 统计数组中成员的个数
echo "追加之前,arr2成员个数 = ${#arr2[*]}"
echo "追加之前,arr2 = ${arr2[*]}"
# 给数组追加一个新的成员
arr2[5]=ff
echo "追加之后,arr2 = ${arr2[@]}"
echo "追加之后,arr2成员个数 = ${#arr2[@]}"
shell中数组的拼接
数组名=(${数组名1[*]} ${数组名2[*])
或者
数组名=(${数组名1[@]} ${数组名2[@])
#!/bin/bash
# your code
arr1=(11 22 33 44)
arr2=(aa bb cc dd)
arr3=(${arr1[*]} ${arr2[*]})
arr4=(${arr2[@]} ${arr1[@]})
echo "arr3数组成员的个数 = ${#arr3[*]}"
echo "arr3数组中的所有的成员 = ${arr3[*]}"
echo "arr4数组成员的个数 = ${#arr4[@]}"
echo "arr4数组中的所有的成员 = ${arr4[@]}"
shell中的算数运算
1. shell本身是不擅长进行算数运算,shell更加擅长命令的指令,文件的处理。
2. shell中的变量本身都属于字符串,因此要在shell中完成算数运算需要使用命令或者运算符号。
3. 在shell中可以使用以下方式完成算数运算
(())
$[]
expr命令
使用(())在shell中完成算数运算
1. 格式
((算数表达式1, 算数表达式2, 算数表达式3, .....))
在(())中可以有多个算数表达式,最后一个表达式的结果作为返回值输出。
2. 接收算数运算的结果
((变量名=算数表达式))
或者
变量名=$((算数表达式))
3. 注意事项
在(())中可以书写复杂的算数表达式
在(())中如果使用变量时,变量前可以加$符号,也可以不加$符号。
在(())中的表达式,运算符前后可以有空格,可以没有空格
#!/bin/bash
# your code
# 在(())可以有多个表达式,最后一个表达式的结果返回
sum=$((100+200, 300+400))
echo "sum = $sum"
# 在(())如果使用变量可以加$,也可不加$
a=100
b=200
sum1=$(($a + $b))
echo "sum1 = $sum1"
# 运算符两边可以有空格
((sum2 = a+b))
echo "sum2 = $sum2"
使用$[]在shell中完成算数运算
1. 格式
$[算数表达式1, 算数表达式2, 算数表达式3, .....]
在$[]中可以有多个算数表达式,最后一个表达式的结果作为返回值输出。
2. 接收算数运算的结果
变量名=$[算数表达式]
3. 注意事项
在使用$[]时,必须使用变量接收返回值
在$[]中可以书写复杂的算数表达式
在$[]中如果使用变量时,变量前可以加$符号,也可以不加$符号。
在$[]中的表达式,运算符前后可以有空格,可以没有空格
#!/bin/bash
# your code
# 在$[]可以有多个表达式,最后一个表达式的结果返回
sum=$[100+200, 300+400]
echo "sum = $sum"
# 在$[]如果使用变量可以加$,也可不加$
a=100
b=200
# 运算符两边可以有空格
sum1=$[$a + $b] # 接收运算的结果
echo "sum1 = $sum1"
# 运算符两边可以没有空格
sum2=$[a+b] # 接收运算的结果
echo "sum2 = $sum2"
# 必须使用变量接收$[]的运算结果
$[100+200] # error
使用expr命令完成算数运算
1. expr是一个shell命令,可以使用man expr查看帮助手册
2. 格式
expr 算数表达式
算数表达式的要求:
1> 在算数表达式中如果使用变量时,必须加$符号,并且推荐大家使用""将变量括起来。
eg:
expr $a + $b # ok
expr "$a" + "$b" # ok
expr a + b # 错误,
2> 在算数表达式中,运算符两边必须添加空格,
eg:
expr 100 + 200 #ok
expr 100+200 # error 语法不报错,整体当成一个字符串输出
原因:expr是一个可执行程序,在expr中有一个main函数,
main函数通过argc获取参数的个数,通过argv是获取哪个参数,
如果表达式的运算两边没有空格,则expr将其当成一个参数处理,
只有运算符两边有空格时,expr才会将其当成多个参数进行解析。
3> 使用expr命令不可以进行自增自减运算
eg:
expr $a++ # error
expr $a-- # error
expr $a + 1 # ok
expr $a - 1 # ok
4> 在expr的表达式中部分运算符需要进行转义
\( \) \< \> \| \& .....
根据expr命令的执行结果,分析运算的符号是否需要转义。
3. 接收expr命令的返回结果
命令置换符: `shell命令` 或者 $(shell命令)
|
|----> 反向单引号,~键盘上的单引号、
命令置换符的作用:可以将命令的执行结果赋值给某个变量。
变量名=`expr 表达式`
变量名=$(expr 表达式)
#!/bin/bash
# your code
a=100
b=200
# 使用变量时,变量名前必须加$符号,
sum1=`expr $a + $b`
echo "sum1 = $sum1"
# 在expr表达式中使用变量时,可以使用双引号括起来
sum2=`expr "$a" + "$b"`
echo "sum2 = $sum2"
# 使用变量时,不加$, 会报错,没有整形的参数
# sum3=`expr a + b` # 执行报错,没有整形的参数
sum3=`expr a+b` # 语法不报错,整体当成字符串输出
echo "sum3 = $sum3"
# 运算符的两边必须添加空格
sum4=`expr 1000 + 2000`
echo "sum4 = $sum4"
sum5=`expr 1000+2000` # 运算符两边没有空格,整体当成一个字符串输出
echo "sum5 = $sum5"
# expr不可以进行自增自减运算
c=`expr $a--` # 语法没有错误,整体当成字符串输出
echo "c = $c"
d=`expr $a + 1`
echo "d = $d"
# expr 对部分运算符需要进行转义
sum=$(expr \( $a + $b \) \* 2)
echo "sum = $sum"
4. expr命令进行算数运算
ARG1 \< ARG2
ARG1 \<= ARG2
ARG1 = ARG2
ARG1 != ARG2
ARG1 \>= ARG2
ARG1 \> ARG2
成立返回1,不成立返回0,使用变量时,给变量加"",部分运算符需要进行转义
ARG1 + ARG2
ARG1 - ARG2
ARG1 \* ARG2
ARG1 / ARG2
ARG1 % ARG2
返回值为运算的结果,使用变量时,给变量加"",部分运算符需要进行转义
ARG1 \| ARG2 ---> 变量的值为空或者为0,都表示假
如果两个表达式都为真时,则返回ARG1的值
如果两个表达式都为假时,则返回0
如果两个表达式有一个为真,则返回为真的表达式的值
ARG1 \& ARG2
只有两个变量的值都为真(变量的值不为0或者非空),
则输出ARG1的值,否则输出0
#!/bin/bash
# your code
# read命令 : 从终端读数据到变量中,类似于scanf函数
# -p参数 : 后边跟的时提示的字符串
read -p "请输入第一个整数 > " num1
read -p "请输入第二个整数 > " num2
ret_val=`expr "$num1" \> "$num2"`
echo "num1 > num2 = $ret_val"
ret_val=`expr "$num1" \<= "$num2"`
echo "num1 <= num2 = $ret_val"
-----------------------------------------
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个整数 > 100
请输入第二个整数 > 200
num1 > num2 = 0
num1 <= num2 = 1
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个整数 > 200
请输入第二个整数 > 150
num1 > num2 = 1
num1 <= num2 = 0
#!/bin/bash
# your code
# read命令 : 从终端读数据到变量中,类似于scanf函数
# -p参数 : 后边跟的时提示的字符串
read -p "请输入第一个字符串 > " num1
read -p "请输入第二个字符串 > " num2
ret_val=`expr "$num1" \| "$num2"`
echo "ret_val = $ret_val"
--------------------------------------------
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > hello
请输入第二个字符串 > world
ret_val = hello
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > hello
请输入第二个字符串 >
ret_val = hello
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 >
请输入第二个字符串 > world
ret_val = world
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 >
请输入第二个字符串 >
ret_val = 0
#!/bin/bash
# your code
# read命令 : 从终端读数据到变量中,类似于scanf函数
# -p参数 : 后边跟的时提示的字符串
read -p "请输入第一个字符串 > " num1
read -p "请输入第二个字符串 > " num2
ret_val=`expr "$num1" \& "$num2"`
echo "ret_val = $ret_val"
--------------------------------------------
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > hello
请输入第二个字符串 > world
ret_val = hello
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > hello
请输入第二个字符串 > 0
ret_val = 0
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > 0
请输入第二个字符串 > world
ret_val = 0
linux@ubuntu:~/DC22101/day03$ bash 10expr.sh
请输入第一个字符串 > 0
请输入第二个字符串 > 0
ret_val = 0
5. expr进行字符串的处理
expr match STRING REGEXP
从STRING字符串中和REGEXP字符串进行比较,如果比较成功返回相同字符的个数,不成功返回0,从第一个字符开始比较
expr substr STRING POS LENGTH
从STRING字符串中截取子字符串,POS从那个位置开始截取,LENGTH截取字符串的长度;
注:STRING字符串的第一个字符的起始编号为1
expr index STRING CHARS
从STRING字符串中查找第一次出现CHARS字符的位置,成功返回字符的编号,没有找到返回0;
如果一个字符串中有多个CHARS,返回第一次出现此字符的位置
注:STRING字符串的第一个字符的起始编号为1
expr length STRING
计算字符串的长度 等价于${#STRING}
#!/bin/bash
# your code
addr=www.baidu.com
# 字符串的匹配
num1=`expr match $addr "www"`
echo "匹配字符串的个数 = $num1"
num2=`expr match $addr "baidu"`
echo "匹配字符串的个数 = $num2"
num3=`expr match $addr "www.hqyj"`
echo "匹配字符串的个数 = $num3"
# 从字符串中截取子字符串
substr=`expr substr $addr 5 5`
echo "substr = $substr"
# 从字符串中查找第一次出现字符的位置
index=`expr index $addr '.'`
echo "index = $index"
# 计算字符串的长度
length=`expr length $addr`
echo "length = $length"
echo "length = ${#addr}"