变量子串常用操作:
表达式 | 含义 |
---|---|
${#string} | $string的长度 |
${string:position} | 在$string中, 从位置$position开始提取子串 |
${string:position:length} | 在$string中, 从位置$position开始提取长度为$length的子串 |
${string#substring} | 从变量$string的开头, 删除最短匹配$substring的子串 |
${string##substring} | 从变量$string的开头, 删除最长匹配$substring的子串 |
${string%substring} | 从变量$string的结尾, 删除最短匹配$substring的子串 |
${string%%substring} | 从变量$string的结尾, 删除最长匹配$substring的子串 |
${string/substring/replacement} | 使用$replacement, 来代替第一个匹配的$substring |
${string//substring/replacement} | 使用$replacement, 代替所有匹配的$substring |
${string/#substring/replacement} | 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring |
${string/%substring/replacement} | 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring |
说明:
$substring可以是一个正则表达式.
返回长度
${#string} :返回$string的长度
字符串截取
字符串截取 格式 使用${}表达式 ${var:起始位置:长度};编号从0开始,可省略 使用expr substr expr substr "$var" 起始位置 长度;起始位置编号从1开始 使用cut工具 echo $var | cut -b 起始位置-结束位置;起始位置编号从1开始
说明:
${string:position} 在$string中, 从位置$position开始提取子串 ${string:position:length} 在$string中, 从位置$position开始提取长度为$length的子串
字符串的匹配删除
格式 ${变量名#*关键词} 从左到右,最短匹配删除;#用来删除头部,*通配 ${变量名##*关键词} 从左到右,最长匹配删除;#用来删除头部,*通配 ${变量名%关键词*} 从右到左,最短匹配删除;%用来删除尾部,*通配 ${变量名%%关键词*} 从右到左,最长匹配删除;%用来删除尾部,*通配
解析:
${string#substring} 从变量$string的开头, 删除最短匹配$substring的子串 ${string##substring} 从变量$string的开头, 删除最长匹配$substring的子串 ${string%substring} 从变量$string的结尾, 删除最短匹配$substring的子串 ${string%%substring} 从变量$string的结尾, 删除最长匹配$substring的子串
文件批量改名
例子:将扩展名.doc改为.txt
#!/bin/bash for FILE in *.doc do mv $FILE ${FILE%.doc}.txt done
字符串的替换
格式 ${var/old/new} 只替换第一个匹配结果 ${var//old/new} 替换全部匹配结果
${string/#substring/replace} 如果$string前缀匹配$substring,就用$replace来代替匹配$substring
${string/%substring/replace} 如果$string后缀匹配$substring,就用$replace来代替匹配$substring
解析:
${string/substring/replacement} 使用$replacement, 来代替第一个匹配的$substring ${string//substring/replacement} 使用$replacement, 代替所有匹配的$substring ${string/#substring/replacement} 如果$string的前缀匹配$substring, 那么就用$replacement来代替匹配到的$substring ${string/%substring/replacement} 如果$string的后缀匹配$substring, 那么就用$replacement来代替匹配到的$substring
依次举例说明:
定义OLDBOY变量,内容为”I am oldboy” I am oldboy 1)返回字符串OLDBOY变量字符串的长度 [root@Web ~]# echo ${#OLDBOY} 11 [root@Web ~]# echo ${OLDBOY} |wc -m 12 2)截取OLDBOY变量字符串从第2个字符之后开始取,默认取后面字符的全部,第2个字符不包括在内。也可理解为删除前面的多少个字符 [root@Web ~]# echo ${OLDBOY:2} am oldboy 3)截取OLDBOY变量字符串从第2个字符之后开始取,取两个字符。 [root@Web ~]# echo ${OLDBOY:2:2} am 提示:类似cut -c参数 [root@Web ~]# echo ${OLDBOY}|cut -c 1-4 I am [root@Web ~]# echo ${OLDBOY}|cut -c 3-4 am 4)从变量$OLDBOY开头开始删除最短匹配”I am”子串 [root@Web ~]# echo ${OLDBOY#I am} oldboy 5)从变量$OLDBOY开头开始删除最长匹配”I am old”子串 [root@Web ~]# echo ${OLDBOY##I am old} boy 6)从变量$OLDBOY结尾开始删除最短匹配oldboy子串 [root@Web ~]# echo ${OLDBOY%oldboy} I am 7)从变量$OLDBOY结尾开始删除最长匹配boy子串 [root@Web ~]# echo ${OLDBOY%%boy} I am old 8)使用etiantian字符串,来代替变量$OLDBOY第一个匹配的oldboy字符串 [root@Web ~]# echo ${OLDBOY/oldboy/etiantian} I am etiantian 9)使用etiantian字符串,来代替变量$OLDBOY结尾匹配的oldboy字符串 [root@Web ~]# echo ${OLDBOY/%oldboy/etiantian} I am etiantian 10)使用He is字符串,来代替从变量$OLDBOY开头开始匹配的I am字符串 [root@Web ~]# echo ${OLDBOY/#I am/He is} He is oldboy
生产场景用法实例:
1)变量结尾删除生产实践:
功能描述如下表:
${string#substring} 从变量$string的开头, 删除最短匹配$substring的子串
批量文件改名案例实践:
问题1:把下面所有的文件名中的finishied内容去掉。 [root@localhost ~]# mkdir /test [root@localhost ~]# cd /test [root@localhost test]# cat a.log stu_102999_2_finish.jpg stu_102999_3_finish.jpg stu_102999_4_finish.jpg [root@localhost test]# for f in `cat a.log`;do touch $f;done [root@localhost test]# ll 总用量 4 -rw-r--r--. 1 root root 72 3月 30 22:24 a.log -rw-r--r--. 1 root root 0 3月 30 22:25 stu_102999_2_finish.jpg -rw-r--r--. 1 root root 0 3月 30 22:25 stu_102999_3_finish.jpg -rw-r--r--. 1 root root 0 3月 30 22:25 stu_102999_4_finish.jpg [root@localhost test]# cat p.sh for f in `ls *.jpg` do mv $f `echo ${f%finish*}.jpg` done [root@localhost test]# ll 总用量 8 -rw-r--r--. 1 root root 72 3月 30 22:24 a.log -rw-r--r--. 1 root root 0 3月 30 22:24 cat -rw-r--r--. 1 root root 64 3月 30 22:49 p.sh -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_2_.jpg -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_3_.jpg -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_4_.jpg
2)变量结尾替换生产实践:
${string/substring/replacement} 使用$replacement, 来代替第一个匹配的$substring
问题:把下面文件的大写扩展名变小写扩展名 [root@localhost test]# cat p.sh for f in `ls *.jpg` do mv $f `echo "${f/%jpg/JPG}"` done [root@localhost test]# sh p.sh [root@localhost test]# ll 总用量 8 -rw-r--r--. 1 root root 72 3月 30 22:24 a.log -rw-r--r--. 1 root root 0 3月 30 22:24 cat -rw-r--r--. 1 root root 63 3月 30 22:52 p.sh -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_2_.JPG -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_3_.JPG -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_4_.JPG
1 命令名称:rename-Rename files
2 命令功能:给文件重命名
3命令语法: rename from to file 提示:这里的用法”from to file”一开始会被大家误解,实际上还是看下面表格吧:
还是看实际例子吧!
准备测试数据:
[root@Web ~]# mkdir /test [root@Web ~]# cd /test [root@Web test]# for f in `seq 9`;do touch foo$f.htm;done [root@Web test]# ls -l 总用量 0 -rw-r--r--. 1 root root 0 4月 12 21:58 foo1.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo2.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo3.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo4.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo5.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo6.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo7.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo8.htm -rw-r--r--. 1 root root 0 4月 12 21:58 foo9.htm [root@localhost test]# rename .JPG .htm *.JPG [root@localhost test]# ll 总用量 8 -rw-r--r--. 1 root root 72 3月 30 22:24 a.log -rw-r--r--. 1 root root 0 3月 30 22:24 cat -rw-r--r--. 1 root root 63 3月 30 22:52 p.sh -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_2_.htm -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_3_.htm -rw-r--r--. 1 root root 0 3月 30 22:48 stu_102999_4_.htm [root@localhost test]# rename 102999 oldboy *.htm [root@localhost test]# ll 总用量 8 -rw-r--r--. 1 root root 72 3月 30 22:24 a.log -rw-r--r--. 1 root root 0 3月 30 22:24 cat -rw-r--r--. 1 root root 63 3月 30 22:52 p.sh -rw-r--r--. 1 root root 0 3月 30 22:48 stu_oldboy_2_.htm -rw-r--r--. 1 root root 0 3月 30 22:48 stu_oldboy_3_.htm
更多批量改名案例,请看老男孩的博文《Linux下批量修改文件名精彩解答案例分享》
https://blog.51cto.com/oldboy/711342
变量初值处理
取值
取值,${var:-word}
若变量var已存在且非null,则返回$var的值 否则返回字串"word",变量var值不变 用途: 如果变量没定义 返回默认值
赋值
赋值,${var:=word}
若变量var已存在且非null,则返回$var的值 否则返回字串"word",并赋值给变量var 用途: 如果变量没定义 给变量赋值
有值时提示
有值时提示,${var:+"提示信息"}
若变量var已存在且非null,则给出提示
否则返回NUll(空值)
用途 : 测试变量是否定义
无值时提示
无值时提示,${var:?"提示信息"}
若变量var已存在且非null,则返回$var的值
否则给出提示信息(若省略,则用默认提示)
用途: 捕捉由于变量未定义所导致的错误
练习:
a、提示输入一个正整数x,求从1到x的和
b、若用户未输入值(直接回车),则赋值x=1
#!/bin/bash read -p "请输入一个正整数:" x x=${x:-1};i=1;SUM=0 while [ $i -le $x ] do let SUM+=i;let i++ done echo "从1到$x的总和是:$SUM"
例题:
mycluster.sh
检查集群中主机的物理连接状态,要求如下
能够设置检查主机的台数 和 检查哪些主机
把不在线主机的ip地址和时间保存到/clusterdir目录下的stat.txt文件里并把不在线主机的ip地址 时间 台数 输出到屏幕上
下面一次举例说明:
(1)${value:-word}
当变量未定义或者值为空时,返回值为word内容,否则返回变量的值
举例:
[zgy@Web ~]$ result=${test:-UNSET}
[zgy@Web ~]$ echo $result
UNSET
[zgy@Web ~]$ echo $test
==>这里是空
结论:当test变量没内容时,就返回了后面的UNSET.
[zgy@Web ~]$ test='oldboy'
[zgy@Web ~]$ result=${test:-UNSET}
[zgy@Web ~]$ echo $result
Oldboy
提示:这个变量可以用来判断变量是否没有定义
(2)${value:=word}
[zgy@Web ~]$ unset result
[zgy@Web ~]$ echo $result
[zgy@Web ~]$ unset test
[zgy@Web ~]$ echo $test
[zgy@Web ~]$ result=${test:=UNSET}
[zgy@Web ~]$ echo $result
UNSET
[zgy@Web ~]$ echo $test
UNSET
[zgy@Web ~]$ test=oldboy
[zgy@Web ~]$ result=${test:=UNSET}
[zgy@Web ~]$ echo $result
oldboy
[zgy@Web ~]$ echo $test
Oldboy
提示:这个变量功能可以解决变量没有定义的问题,确保变量始终有值
(3)${value:?”word”}
[zgy@Web ~]$ echo ${value:?"not defined"}
-bash: value: not defined
[zgy@Web ~]$ value=1
[zgy@Web ~]$ echo ${value:?"not defined"}
1
[zgy@Web ~]$ unset value
[zgy@Web ~]$ echo ${value:?"not defined"}
-bash: value: not defined
提示:用于捕捉由于未定义而导致的错误,如:"not defined"。
(4)${var:+word}
[zgy@Web ~]$ r=${value:+1}
[zgy@Web ~]$ echo $r
[zgy@Web ~]$ value=oldboy
[zgy@Web ~]$ echo $r
[zgy@Web ~]$ r=${value:+1}
[zgy@Web ~]$ echo $r
1
提示:此功能可用于测试变量是否存在。
(5){value:-word}去掉冒号
[zgy@Web ~]$ httpd=${HTTPD-/usr/sbin/httpd} [zgy@Web ~]$ pidfile=${PIDFILE-/var/run/httpd,pid} [zgy@Web ~]$ echo $httpd $pidfile /usr/sbin/httpd /var/run/httpd,pid [zgy@Web ~]$ echo $HTTPD $PIDFILE
结论:变量没定义就用-号后面的替代
(6)应用例子:/etc/init.d/httpd(注意红色部分)
apachectl=/usr/sbin/apachectl httpd=${HTTPD-/usr/sbin/httpd} prog=httpd pidfile=${PIDFILE-/var/run/httpd/httpd.pid} lockfile=${LOCKFILE-/var/lock/subsys/httpd} RETVAL=0
提示:用yum安装的httpd
系统服务crond脚本使用案例:/etc/init.d/crond
如图:
(2)${value:=word}
与前者类似,只是若变量未定义或者值为空时,在返回word的值的同时将word赋值给value
[root@Web ~]# OLD=${value:=word} [root@Web ~]# echo $OLD word [root@Web ~]# echo $value word [root@Web ~]# value="test" [root@Web ~]# OLD=${value:=word} [root@Web ~]# echo $OLD test [root@Web ~]# echo $value test
注:变量替换的值也可以是``括起来的命令:$USERDIR={$Mydir:-`pwd`}
(3)${value:?message}
若变量以赋值的话,正常替换。否则将消息message送到标准错误输出(若此替换出现在shell程序中,那么该程序将中止运行)
生产应用场景:
1)/etc/init.d/httpd
2)/etc/init.d/crond
3)对变量的路径进行操作,最好先判断路径是否为空。特别是删除操作,容易有危险。
[root@Web ~]#sed -i ‘1d’d.sh [root@Web ~]# cat d.sh path=/server/backup find ${path:=/tmp/} -name “*.tar.gz” -type f | xargs rm -f [root@Web ~]#sh -x d.sh
变量的处理计算变量长度与其他不同方法的耗时对比:
[root@Web ~]# chars=`seq -s " " 100` [root@Web ~]# echo $chars 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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 [root@Web ~]# echo ${#chars} 291 [root@Web ~]# echo $chars|wc -m 292 [root@Web ~]# echo $(expr length "$chars") 291 [root@Web ~]# time for i in $(seq 11111);do count=${#chars};done; real 0m0.671s user 0m0.950s sys 0m0.002s [root@Web ~]# time for i in $(seq 11111);do count=`echo ${chars}|wc -m`;done; real 0m27.419s user 0m1.021s sys 0m4.189s [root@Web ~]# time for i in $(seq 11111);do count=`echo expr length "${chars}"`;done; real 0m6.513s user 0m0.346s sys 0m1.376s
我们看到速度相差几十到上百倍,一般情况调用外部命令处理,与内置功能操作性能相差较大。在shell编程中,我们应尽量用内置操作或函数完成。
变量处理替换的一些参考资料
man bash变量处理大全<==学习要尽量去找一手资料 http://www.cnblogs.com/chengmo/archive/2010/10/02/1841355.html