zhangguanzhang's Blog

shell的字符串截取

字数统计: 1.2k阅读时长: 5 min
2017/04/15

shell的字符串截取

提取子串

${string:position}
在$string中从位置$position开始提取子串.
如果$string是”*”或者”@”, 那么将会提取从位置$position开始的位置参数.

1
2
3
4
5
6
7
[root@guan temp]# 
[root@guan temp]# cat>test.sh<<'eof'
> #!/bin/bash
> echo ${*:3}
> eof
[root@guan temp]# sh test.sh 1 2 3 4 5 6
3 4 5 6

${string:position:length}
在$string中从位置$position开始提取$length长度的子串.


    1 stringZ=abcABC123ABCabc
    2 # 0123456789.....
    3 # 0-based indexing.
    4
    5 echo ${stringZ:0} # abcABC123ABCabc
    6 echo ${stringZ:1} # bcABC123ABCabc
    7 echo ${stringZ:7} # 23ABCabc
    8
    9 echo ${stringZ:7:3} # 23A
    10  # 提取子串长度为3.
    11
    12
    13
    14 # 能不能从字符串的右边(也就是结尾) 部分开始提取子串?
    15
    16 echo ${stringZ:-4} # abcABC123ABCabc
    17 # 默认是提取整个字符串, 就象${parameter:-default} 一样.
    18 # 然而 . . .
    19
    20 echo ${stringZ:(-4)} # Cabc
    21 echo ${stringZ: -4} # Cabc
    22 # 这样, 它就可以工作了.
    23 # 使用圆括号或者添加一个空格可以"转义"这个位置参数.
    24
    25 # 感谢, Dan Jacobson, 指出这点.

如果$string参数是”*”或”@”, 那么将会从$position位置开始提取$length个位置参数, 但是由于
可能没有$length个位置参数了, 那么就有几个位置参数就提取几个位置参数.


    1 echo ${*:2} # 打印出第2个和后边所有的位置参数.
    2 echo ${@:2} # 同上.
    3
    4 echo ${*:2:3} # 从第2个开始, 连续打印3个位置参数.





子串削除

${string#substring}

从$string的开头位置截掉最短匹配的$substring.

${string##substring}

从$string的开头位置截掉最长匹配的$substring.

	1 stringZ=abcABC123ABCabc
    2 #|----|
    3 #|----------|
    4
    5 echo ${stringZ#a*C} # 123ABCabc
    6 # 截掉'a' 到'C' 之间最短的匹配字符串.
    7
    8 echo ${stringZ##a*C} # abc
    9 # 截掉'a' 到'C' 之间最长的匹配字符串.

${string%substring}

从$string的结尾位置截掉最短匹配的$substring.

${string%%substring}

从$string的结尾位置截掉最长匹配的$substring.

以上摘录自高级bash脚本编写指南

记忆方法:#是左边开始,%是右边开始,单个符号是最短,俩符号就是最长

来实际操作一遍

[root@guan ~]# str=resources/mapper/jxc/authority/IstorageMapper.xml

从例子里可以看出来可以用通配符,那随便测试下
首先是#测试
去掉r到第一个s

[root@guan ~]# echo ${str#r*s}
ources/mapper/jxc/authority/IstorageMapper.xml

去掉r到最后一个s

[root@guan ~]# echo ${str##r*s}
torageMapper.xml

删掉第一部分路径

[root@guan ~]# echo ${str#*/}
mapper/jxc/authority/IstorageMapper.xml

提取基本文件名

[root@guan ~]# echo ${str##*/}
IstorageMapper.xml

提取后缀

[root@guan ~]# echo ${str#*.}
xml

其次%测试
删掉最后的文件名部分,即提取文件所在路径

[root@guan ~]# echo ${str%/*}
resources/mapper/jxc/authority

也可以

[root@guan ~]# echo ${str%/*l}
resources/mapper/jxc/authority

提取顶层路径

[root@guan ~]# echo ${str%%/*}
resources

也可以对变量值里的字符串作替换:
假设我们定义了一个变量为:
file=/dir1/dir2/dir3/my.file.txt

${file/dir/path}:将第一个dir 替换为path:/path1/dir2/dir3/my.file.txt
${file//dir/path}:将全部dir 替换为 path:/path1/path2/path3/my.file.txt

留下一个练习题大家做做看
最后前不久在群里看到有人说怎么把文件夹下面的文件全部改为包含组名
例如a.txt组是test,那么变更后就是a[test].txt
所有文件改成这样的类型
答案点我

然后是
${参数^模式}
${参数^^模式}
${参数,模式}
${参数,,模式}
上面四个是把参数扩展转换字母大小写
符号在上面就是转换为大写,下面就是转换为小写

注意:

  • 模式只能是一个字符或者空,其余的一律不转换
  • 一个符号的情况下,无论模式有还是无,只参数的第一个字符
  • 俩个符号的情况下,会转换所有字符
[root@guan temp]# str=`pwd`/test;echo $str
/root/temp/test
[root@guan temp]# echo ${str^}
Test/root/temp
[root@guan temp]# echo ${str^t}
Test/root/temp
[root@guan temp]# echo ${str^e}  #此处不转换
test/root/temp
[root@guan temp]# echo ${str^^}
TEST/ROOT/TEMP
[root@guan temp]# echo ${str^^t}
TesT/rooT/Temp
[root@guan temp]# echo ${str^^e}
tEst/root/tEmp
---------------------------------
[root@guan temp]# str=TEST/ROOT/TEMP
[root@guan temp]# echo ${str,}
tEST/ROOT/TEMP
[root@guan temp]# echo ${str,T}
tEST/ROOT/TEMP
[root@guan temp]# echo ${str,e}  #此处不转换
TEST/ROOT/TEMP
[root@guan temp]# echo ${str,,T}
tESt/ROOt/tEMP
[root@guan temp]# echo ${str,,E}
TeST/ROOT/TeMP
[root@guan temp]# echo ${str,,}
test/root/temp
CATALOG