# shell 语法 为了确保使用合适的shell来执行,需加入一行“幻行”作为脚本第一行。 我们使用sh来运行脚本 #!/bin/bash 启动非交互式的shell:(filename是包含可执行命令的文件的名称) /bin/bash filename ## 常见shell Unix/Linux上常见的shell脚本解释器有**bash、sh、csh、ksh**等,习惯上把它们称作一种shell。我们常说有多少种shell,其实说的是shell脚本解释器。 - bash - 是Linux标准默认的shell。内部命令一共有40个。 - bash完全兼容sh,也就是说,用sh写的脚本可以不加修改的在bash中执行。 - Linux使用它作为默认的shell是因为它有诸如以下的特色:可以使用类似DOS下面的doskey的功能,用方向键查阅和快速输入并修改命令。自动通过查找匹配的方式给出以某字符串开头的命令。包含了自身的帮助功能,你只要在提示符下面键入help就可以得到相关的帮助。 - sh - Unix 标准默认的shell。 - ash - Linux中占用系统资源最少的一个小shell,它只包含24个内部命令,因而使用起来很不方便。 - csh - 是Linux比较大的内核,共有52个内部命令。该shell其实是指向/bin/tcsh这样的一个shell,也就是说,csh其实就是tcsh。 - ksh - 共有42条内部命令。该shell最大的优点是几乎和商业发行版的ksh完全兼容,这样就可以在不用花钱购买商业版本的情况下尝试商业版本的性能了。 ## shell变量 定义变量时,变量名不加美元符号($)。**变量名和等号之间不能有空格**。变量名的命名须遵循如下规则: - 首个字符必须为字母(a-z,A-Z)。 - 中间不能有空格,可以使用下划线(_)。 - 不能使用标点符号。 - 不能使用bash里的关键字(可用help命令查看保留关键字)。 - 使用一个定义过的变量,只要在变量名前面加美元符号($)即可。变量名外面的花括号是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界。**推荐给所有变量加上花括号,这是个好的编程习惯。** - 已定义的变量,可以被重新定义。 - 使用**readonly**命令可以将变量定义为只读变量,只读变量的值不能被改变。 - 使用 **unset** 命令可以删除变量。变量被删除后不能再次使用;unset 命令不能删除只读变量。 ```bash testnum=1 testchar="abcdefg" echo $testnum echo ${testnum} testchar="abcdefghijklmn" #重新定义 readonly testnum #定义为只读变量 unset testchar #删除变量 ``` ## shell 特殊变量 特殊变量列表 - $0 当前脚本的文件名 - $n 传递给脚本或函数的参数。n 是一个数字,表示第几个参数。例如,第一个参数是$1,第二个参数是$2。 - $# 传递给脚本或函数的参数个数。 - $* 传递给脚本或函数的所有参数。 - $@ 传递给脚本或函数的所有参数。被双引号(" ")包含时,与 $* 稍有不同。 - $? 上个命令的退出状态,或函数的返回值。 - $$ 当前shell进程ID。对于 shell 脚本,就是这些脚本所在的进程ID。 $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。但是当它们被双引号(" ")包含时,"$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;"$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数。 变量替换可以根据变量的状态(是否为空、是否定义等)来改变它的值 可以使用的变量替换形式: - ${var} 变量本来的值 - ${var:-word} 如果变量 var 为空或已被删除(unset),那么返回 word,但不改变 var 的值。 - ${var:=word} 如果变量 var 为空或已被删除(unset),那么返回 word,并将 var 的值设置为 word。 - ${var:?message} 如果变量 var 为空或已被删除(unset),那么将消息 message 送到标准错误输出,可以用来检测变量 var 是否可以被正常赋值。若此替换出现在shell脚本中,那么脚本将停止运行。 - ${var:+word} 如果变量 var 被定义,那么返回 word,但不改变 var 的值。 ## shell 数组 bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数组中的元素要利用下标,下标可以是整数或算术表达式,其值应大于或等于0。 **定义数组** 在shell中,用括号来表示数组,数组元素用“空格”符号分割开。可以不使用连续的下标,而且下标的范围没有限制。定义数组的一般形式为: ```bash array_name=(value1 ... valuen) ``` **读取数组** 读取数组元素值的一般格式是: ```bash ${array_name[index]} ``` 使用@ 或 * 可以获取数组中的所有元素,例如: ```bash ${array_name[*]} ${array_name[@]} ``` **获取数组的长度** 获取数组长度的方法与获取字符串长度的方法相同,例如: ```bash # 取得数组元素的个数 length=${#array_name[@]} # 或者 length=${#array_name[*]} # 取得数组单个元素的长度 lengthn=${#array_name[n]} ``` ## 置换和通配 ```bash * #匹配0个或多个任意字符 ? #匹配一个任意字符 [characters] #匹配给定的characters中的任意一个字符 `xxx` #反引号,反引号允许将shell命令的输出赋值给变量。xxx可以是一个简单的命令,一个管道|或者是一个列表;(隔开)。 ``` ## 输入和输出 **输出重定向** 为了把一个命令或脚本的输出重定向到文件而不是输出到STDOUT,要使用输出重定向操作符(>)如下所示: cmd > file 或 list > file 第一种形式将命令cmd的输出重定向到由file指定的文件file,而第二种形式把命令列表list的输出重定向到由file指定的文件file。 如果指定的文件file存在,它的内容将被覆盖;如果file不存在,则它会被生成。 **追加到文件** 简单地把命令的输出重定向到一个文件从而覆盖该文件经常不是我们想要的。操作符(>>)可以把输出追加到文件中。 cmd >> file 或 list >> file 命令的输出被追加到文件的尾部。如果文件不存在,它将被生成。 如果希望执行某个命令,但又不希望在屏幕上显示输出结果,那么可以将输出重定向到 **/dev/null**。/dev/null 是一个特殊的文件,写入到它的内容都会被丢弃;如果尝试从该文件读取内容,那么什么也读不到。但是 /dev/null 文件非常有用,将命令的输出重定向到它,会起到”禁止输出“的效果。 一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件: - 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。 - 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。 - 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。 ## 引用 - 反斜线(\),单引号(' '),双引号(" ") - 单独反斜线通常用于实现其后字符的引用。 - 全部需要引用处理的元字符 * ? [ ] ' " \ $ ; & ( ) | ^ ! # newline tab - 字符串用单引号实现引用处理时,字符串中所有元字符失去它们的特殊含义,并当作它们的本意来处理。 - 双引号禁止了除了$和'以外的所有元字符,因此变量和命令域在一个引用处理的字符串中都起作用。 ```bash #单引号 str='this is a string' #单引号字符串的限制:单引号里的任何字符都会原样输出,单引号字符串中的变量是无效的;单引号字串中不能出现单引号(对单引号使用转义符后也不行)。 #双引号 your_name='qinjx' str="Hello, I know your are \"$your_name\"! \n" #双引号的优点:双引号里可以有变量;双引号里可以出现转义字符 #拼接字符串 your_name="qinjx" greeting="hello, "$your_name" !" greeting_1="hello, ${your_name} !" echo $greeting $greeting_1 #获取字符串长度 string="abcd" echo ${#string} #输出 4 #提取子字符串 string="alibaba is a great company" echo ${string:1:4} #输出liba #查找子字符串 string="alibaba is a great company" echo `expr index "$string" is` ``` ## shell运算符(test命令) 开括号([)通常用作test的缩写: [ expression ] 这里expr是任何一种test所能理解的有效表达式。 闭括号(])是必需的,并且在闭括号(])前和开括号([)后都需要空格。 Bash 支持很多运算符,包括算数运算符、关系运算符、布尔运算符、字符串运算符和文件测试运算符。 原生bash不支持简单的数学运算,但是可以通过其他命令来实现,例如 awk 和 expr,expr 最常用。 expr 是一款表达式计算工具,使用它能完成表达式的求值操作。 **NOTE** - 表达式和运算符之间要有空格,例如 2+2 是不对的,必须写成 2 + 2。 - 完整的表达式要被 ` ` 包含,注意这个字符不是常用的单引号,在 Esc 键下边。 算术运算符列表 ```bash #运算符 说明 举例 + 加法 `expr $a + $b` 结果为 30。 - 减法 `expr $a - $b` 结果为 10。 * 乘法 `expr $a \* $b` 结果为 200。 / 除法 `expr $b / $a` 结果为 2。 % 取余 `expr $b % $a` 结果为 0。 = 赋值 a=$b 将把变量 b 的值赋给 a。 == 相等。用于比较两个数字,相同则返回 true。 [ $a == $b ] 返回 false。 != 不相等。用于比较两个数字,不相同则返回 true。 [ $a != $b ] 返回 true。 ``` **注意:条件表达式要放在方括号之间,并且要有空格,例如 [$a==$b] 是错误的,必须写成 [ $a == $b ]。** 关系运算符只支持数字,不支持字符串,除非字符串的值是数字。 关系运算符列表(数字比较操作符) ```bash #运算符 说明 举例 -eq 检测两个数是否相等,相等返回 true。 [ $a -eq $b ] 返回 true。 -ne 检测两个数是否相等,不相等返回 true。 [ $a -ne $b ] 返回 true。 -gt 检测左边的数是否大于右边的,如果是,则返回 true。 [ $a -gt $b ] 返回 false。 -lt 检测左边的数是否小于右边的,如果是,则返回 true。 [ $a -lt $b ] 返回 true。 -ge 检测左边的数是否大等于右边的,如果是,则返回 true。 [ $a -ge $b ] 返回 false。 -le 检测左边的数是否小于等于右边的,如果是,则返回 true。 [ $a -le $b ] 返回 true。 ``` 布尔运算符列表 ```bash 运算符 说明 举例 ! 非运算,表达式为 true 则返回 false,否则返回 true。 [ ! false ] 返回 true。 -o 或运算,有一个表达式为 true 则返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。 -a 与运算,两个表达式都为 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。 ``` 字符串运算符列表 ```bash 运算符 说明 举例 = 检测两个字符串是否相等,相等返回 true。 [ $a = $b ] 返回 false。 != 检测两个字符串是否相等,不相等返回 true。 [ $a != $b ] 返回 true。 -z 检测字符串长度是否为0,为0返回 true。 [ -z $a ] 返回 false。 -n 检测字符串长度是否为0,不为0返回 true。 [ -z $a ] 返回 true。 str 检测字符串是否为空,不为空返回 true。 [ $a ] 返回 true。 ``` 文件测试运算符用于检测 Unix 文件的各种属性。 文件测试运算符列表 ```bash 操作符 说明 举例 -b file 检测文件是否是块设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。 -c file 检测文件是否是字符设备文件,如果是,则返回 true。 [ -b $file ] 返回 false。 -d file 检测文件是否是目录,如果是,则返回 true。 [ -d $file ] 返回 false。 -e file 检测文件(包括目录)是否存在,如果是,则返回 true。 [ -e $file ] 返回 true。 -f file 检测文件是否是普通文件(既不是目录,也不是设备文件),如果是,则返回 true。 [ -f $file ] 返回 true。 -g file 检测文件是否设置了 SGID 位,如果是,则返回 true。 [ -g $file ] 返回 false。 -h file 当file存在并且是符号链接文件时返回真,该选项在一些老系统上无效 -k file 检测文件是否设置了粘着位(Sticky Bit),如果是,则返回 true。 [ -k $file ] 返回 false。 -p file 检测文件是否是具名管道,如果是,则返回 true。 [ -p $file ] 返回 false。 -u file 检测文件是否设置了 SUID 位,如果是,则返回 true。 [ -u $file ] 返回 false。 -r file 检测文件是否可读,如果是,则返回 true。 [ -r $file ] 返回 true。 -w file 检测文件是否可写,如果是,则返回 true。 [ -w $file ] 返回 true。 -x file 检测文件是否可执行,如果是,则返回 true。 [ -x $file ] 返回 true。 -s file 检测文件是否为空(文件大小是否大于0),不为空返回 true。 [ -s $file ] 返回 true。 -o file 当由file指定的文件或目录存在并且被当前进程的有效用户ID所指定的用户拥有时返回真 ``` ---- ## Shell if else语句 if 语句通过关系运算符判断表达式的真假来决定执行哪个分支。shell 有三种 if ... else 语句: - if ... fi 语句; - if ... else ... fi 语句; - if ... elif ... else ... fi 语句。 ### if ... fi 语句 if ... fi 语句的语法: ```bash if [ expression ] then Statement(s) to be executed if expression is true fi ``` 如果 expression 返回 true,then 后边的语句将会被执行;如果返回 false,不会执行任何语句。 最后必须以 fi 来结尾闭合 if,fi 就是 if 倒过来拼写。 **注意:expression 和方括号([ ])之间必须有空格,否则会有语法错误。** ### if ... else ... fi 语句 if ... else ... fi 语句的语法: ```bash if [ expression ] then Statement(s) to be executed if expression is true else Statement(s) to be executed if expression is not true fi ``` 如果 expression 返回 true,那么 then 后边的语句将会被执行;否则,执行 else 后边的语句。 ### if ... elif ... fi 语句 if ... elif ... fi 语句可以对多个条件进行判断,语法为: ```bash if [ expression 1 ] then Statement(s) to be executed if expression 1 is true elif [ expression 2 ] then Statement(s) to be executed if expression 2 is true elif [ expression 3 ] then Statement(s) to be executed if expression 3 is true else Statement(s) to be executed if no expression is true fi ``` 哪一个 expression 的值为 true,就执行哪个 expression 后面的语句;如果都为 false,那么不执行任何语句。 ## shell case esac语句 case语句: ```bash case word in pattern1) list1;; pattern2) list2;; …… patternN) listN;; *) list;; esac ``` case工作方式如上所示。取值后面必须为关键字 in,每一模式必须以右括号结束。取值可以为变量或常数。 字符串变量word与从pattern1到patternN的所有模式一一比较。当找到一个匹配的模式后就执行跟在匹配模式后的list。 取值将检测匹配的每一个模式。一旦模式匹配,则执行完匹配模式相应命令后不再继续其他模式。如果无一匹配模式,使用星号 * 捕获该值,再执行后面的命令。 当一个list执行完了,专用命令**;;**表明流应该跳转到case语句的最后。**;;**类似于C程序中的break指令。 如果找不到匹配的模式,case语句就不做任何动作。至少要有一条模式,堆模式的最大数目没有限制。 ## shell for循环 for循环一般格式为: ```bash for 变量 in 列表 do command1 command2 ... commandN done ``` 列表是一组值(数字、字符串等)组成的序列,每个值通过空格分隔。每循环一次,就将列表中的下一个值赋给变量。 in 列表是可选的,如果不用它,for 循环使用命令行的位置参数。 例如,顺序输出当前列表中的数字: ```bash for loop in 1 2 3 4 5 do echo "The value is: $loop" done ``` ```bash #!/bin/bash for varible1 in {1..5} #for varible1 in 1 2 3 4 5 do echo "Hello, Welcome $varible1 times " done ``` ```bash #!/bin/bash sum=0 for i in {1..100..2} #通过i的按步数2不断递增 do let "sum+=i" done echo "sum=$sum" ``` 显示主目录下以 .bash 开头的文件: ```bash #!/bin/bash for FILE in $HOME/.bash* do echo $FILE done ``` ```bash #!/bin/bash #for循环对字符串进行操作,例如通过for循环显示当前目录下所有的文件。 for file in $( ls ) #for file in * #通配符*产生文件名扩展,匹配当前目录下的所有文件 do echo "file: $file" done ``` ```bash #!/bin/bash for((integer = 1; integer <= 5; integer++)) do echo "$integer" done sum=0 for(( i = 1; i <= 100; i = i + 2 )) do let "sum += i" done echo "sum=$sum" ``` ## shell while循环 while循环用于不断执行一系列命令,也用于从输入文件中读取数据;命令通常为测试条件。其格式为: ```bash while cmd do list done ``` 命令执行完毕,控制返回循环顶部,从头开始直至测试条件为假。 这里cmd是一个单一的命令,而list是一个或多个命令列表。command可以是任何合法的命令,通常是test表达式。 do和done关键字并不认为是while循环的主体,因为shell只使用它们来检查while循环的开始和结束。 ```bash #!/bin/bash sum=0 i=1 while(( i <= 100 )) do let "sum+=i" let "i += 2" done echo "sum=$sum" ``` ```bash #!/bin/bash echo "Please input the num " read num factorial=1 while [ "$num" -gt 0 ] do let "factorial= factorial*num" let "num--" done echo "The factorial is $factorial" ``` while循环可以和输入重定向结合,从文件中一次读出一行。基本语法如下: ```bash while read LINE do : #manipulate file here done < file ``` 在whlie的主体中,可以操作特定文件的每一行。一个简单的例子如下: ```bash while read LINE do case $LINE in *root*) echo $LINE ;; esac done < /ect/passwd ``` 这里只有在文件/ect/passwd中包含root的行被显示: 输出如下: root:x:0:1:Super-User:/:/sbin/sh ## shell until循环 until 循环执行一系列命令直至条件为 true 时停止。until 循环与 while 循环在处理方式上刚好相反。一般while循环优于until循环,但在某些时候,也只是极少数情况下,until 循环更加有用。 until 循环格式为: ```bash until command do Statement(s) to be executed until command is true done ``` command 一般为条件表达式,如果返回值为 false,则继续执行循环体内的语句,否则跳出循环。 例如,使用 until 命令输出 0 ~ 9 的数字: ```bash #!/bin/bash a=0 until [ ! $a -lt 10 ] do echo $a a=`expr $a + 1` done ``` ## shell break和continue命令 在循环过程中,有时候需要在未达到循环结束条件时强制跳出循环,像大多数编程语言一样,Shell也使用 break 和 continue 来跳出循环。 **break命令** break命令允许跳出所有循环(终止执行后面的所有循环)。 下面的例子中,脚本进入死循环直至用户输入数字大于5。要跳出这个循环,返回到shell提示符下,就要使用break命令。 ```bash #!/bin/bash while : do echo -n "Input a number between 1 to 5: " read aNum case $aNum in 1|2|3|4|5) echo "Your number is $aNum!" ;; *) echo "You do not select a number between 1 to 5, game is over!" break ;; esac done ``` 在嵌套循环中,break 命令后面还可以跟一个整数,表示跳出第几层循环。例如: ```bash break n ``` 表示跳出第 n 层循环。 下面是一个嵌套循环的例子,如果 var1 等于 2,并且 var2 等于 0,就跳出循环: ```bash #!/bin/bash for var1 in 1 2 3 do for var2 in 0 5 do if [ $var1 -eq 2 -a $var2 -eq 0 ] then break 2 else echo "$var1 $var2" fi done done ``` **continue命令** continue命令与break命令类似,只有一点差别,它不会跳出所有循环,仅仅跳出当前循环。 ```bash #!/bin/bash while : do echo -n "Input a number between 1 to 5: " read aNum case $aNum in 1|2|3|4|5) echo "Your number is $aNum!" ;; *) echo "You do not select a number between 1 to 5!" continue echo "Game is over!" ;; esac done ````` 同样,continue 后面也可以跟一个数字,表示跳出第几层循环。 再看一个 continue 的例子: ```bash #!/bin/bash NUMS="1 2 3 4 5 6 7" for NUM in $NUMS do Q=`expr $NUM % 2` if [ $Q -eq 0 ] then echo "Number is an even number!!" continue fi echo "Found odd number" done ``` ---- ## 常用技巧 ```bash #得到进程的个数 ps -e | grep -c "所查进程名字" #整型变量自增(加1)的几种方法 a=1 a=$(($a+1)) a=$[$a+1] a=`expr $a + 1` let a++ let a+=1 ((a++)) #字符串的替换 filename="root_v5.34.36" name=`expr $filename | sed 's/_v/-/g'` #将 _v 换乘 - #判断当前是否为root用户 #whoami(显示当前用户的用户名) if [ `whoami` = "root" ];then echo "root用户!" else echo "非root用户!" fi #id -u (显示当前用户的uid) if [ `id -u` -eq 0 ];then echo "root用户!" else echo "非root用户!" fi #获取CPU核心数 cat /proc/cpuinfo | grep processor | wc -l #判断文件是否存在 myPath="/var/log/httpd/" myFile="/var /log/httpd/access.log" # 这里的-x 参数判断$myPath是否存在并且是否具有可执行权限 if [ ! -x "$myPath"]; then mkdir "$myPath" fi # 这里的-d 参数判断$myPath是否存在 if [ ! -d "$myPath"]; then mkdir "$myPath" fi # 这里的-f参数判断$myFile是否存在 if [ ! -f "$myFile" ]; then touch "$myFile" fi # 其他参数还有-n,-n是判断一个变量是否是否有值 if [ ! -n "$myVar" ]; then echo "$myVar is empty" exit 0 fi # 两个变量判断是否相等 if [ "$var1" = "$var2" ]; then echo '$var1 eq $var2' else echo '$var1 not eq $var2' fi #shell判断文件夹是否存在 #如果文件夹不存在,创建文件夹 if [ ! -d "/myfolder" ]; then mkdir /myfolder fi #shell判断文件,目录是否存在或者具有权限 folder="/var/www/" file="/var/www/log" # -x 参数判断 $folder 是否存在并且是否具有可执行权限 if [ ! -x "$folder"]; then mkdir "$folder" fi # -d 参数判断 $folder 是否存在 if [ ! -d "$folder"]; then mkdir "$folder" fi # -f 参数判断 $file 是否存在 if [ ! -f "$file" ]; then touch "$file" fi # -n 判断一个变量是否有值 if [ ! -n "$var" ]; then echo "$var is empty" exit 0 fi # 判断两个变量是否相等 if [ "$var1" = "$var2" ]; then echo '$var1 eq $var2' else echo '$var1 not eq $var2' fi ``` ```bash ## shell截取字符串的方法 #shell中截取字符串的方法有很多中, ${expression} #一共有9种使用方法。 ${parameter:-word} ${parameter:=word} ${parameter:?word} ${parameter:+word} #上面4种可以用来进行缺省值的替换。 ${#parameter} #上面这种可以获得字符串的长度。 ${parameter%word} #最小限度从后面截取word ${parameter%%word} #最大限度从后面截取word ${parameter#word} #最小限度从前面截取word ${parameter##word} #最大限度从前面截取word #上面4个就是用来截取字符串的方法了。 #有了这四种用法就不必使用cut命令来截取字符串了 # 1、使用 # 号操作符。用途是从左边开始删除第一次出现子字符串即其左边字符,保留右边字符。用法为#*substr,例如: str='http://www.你的域名.com/cut-string.html' echo ${str#*//} #得到的结果为www.你的域名.com/cut-string.html,即删除从左边开始到第一个"//"及其左边所有字符 #2、使用 ## 号操作符。用途是从左边开始删除最后一次出现子字符串即其左边字符,保留右边字符。用法为##*substr,例如: str='http://www.你的域名.com/cut-string.html' echo ${str##*/} #得到的结果为cut-string.html,即删除最后出现的"/"及其左边所有字符 #3、使用 % 号操作符。用途是从右边开始删除第一次出现子字符串即其右边字符,保留左边字符。用法为%substr*,例如: str='http://www.你的域名.com/cut-string.html' echo ${str%/*} #得到的结果为http://www.你的域名.com,即删除从右边开始到第一个"/"及其右边所有字符 #4、使用 %% 号操作符。用途是从右边开始删除最后一次出现子字符串即其右边字符,保留左边字符。用法为%%substr*,例如: str='http://www.你的域名.com/cut-string.html' echo ${str%%/*} #得到的结果为http://www.你的域名.com,即删除从右边开始到最后一个"/"及其右边所有字符 #1、从左边第几个字符开始以及字符的个数,用法为:start:len,例如: str='http://www.你的域名.com/cut-string.html' echo ${var:0:5} #其中的 0 表示左边第一个字符开始,5 表示字符的总个数。 #结果是:http: #2、从左边第几个字符开始一直到结束,用法为:start,例如: str='http://www.你的域名.com/cut-string.html' echo ${var:7} #其中的 7 表示左边第8个字符开始 #结果是:www.你的域名.com/cut-string.html #3、从右边第几个字符开始以及字符的个数,用法:0-start:len,例如: str='http://www.你的域名.com/cut-string.html' echo ${str:0-15:10} #其中的 0-6 表示右边算起第6个字符开始,10 表示字符的个数。 #结果是:cut-string #4、从右边第几个字符开始一直到结束,用法:0-start,例如: str='http://www.你的域名.com/cut-string.html' echo ${str:0-4} #其中的 0-6 表示右边算起第6个字符开始,10 表示字符的个数。 #结果是:html #注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示) ``` 参考网站: > http://c.biancheng.net/cpp/shell/ > http://blog.csdn.net/ithomer/article/details/6836382 > shell:(精通shell编程(第二版)[美]Srirange Veeraghavan著,卢涛译,人民邮电出版社,ISBN7-115-11141-3/TP*3354) > http://www.cnblogs.com/xwdreamer/p/3823463.html