zoukankan      html  css  js  c++  java
  • Shell中截取字符串的用法小结

    在日常运维工作中,经常会碰到需要在一个字符串中截取我们需要的某些字符的需求,之前介绍了Shell脚本中数组的使用方法,这里介绍下基于字符串的截取的方法。在shell中截取字符串的方法有下面集中:
    ${var#*/}
    ${var##*/}
    ${var%/*}
    ${var%%/*}
    ${var:start:len}
    ${var:start}
    ${var:0-start:len}
    ${var:0-start}

    可以总结为:
    ********************************************
    #         删除最小的匹配前缀
    ##       删除最大的匹配前缀
    %        删除最小的匹配后缀
    %%     删除最大的匹配后缀
    ********************************************

    1)获得字符串的长度
    语法:${#var}   

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    length=${#str}
    echo "length: [${length}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh 
    string: [http://www.kevin.com/shibo/anhuigrace]
    length: [37]
    

    2)使用 # 和 ## 获取尾部子字符串(*号在分隔符的前面,就去掉其之前的字符)
    2.1) # 最小限度从前面截取word
    语法:${parameter#*word} , 即截取 "第一个分隔符word及其之前的字符全部删掉"后的字符

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #分割符为'/'
    substr=${str#*/}
    echo "substr: [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh 
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr: [/www.kevin.com/shibo/anhuigrace]
    

    2.2)## 最大限度从前面截取word
    语法:${parameter##*word},即截取 "最后一个分隔符word及其之前的字符全部删掉"后的字符

    [root@kevin~]# cat test.sh  
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #分割符为'/'
    substr=${str##*/}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh  
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [anhuigrace]
    

    3)使用 % 和 %% 获取头部子字符串 (*在分隔符的后面,就去掉其之后的字符)
    3.1)% 最小限度从后面截取word
    语法:${parameter%word*},即截取 "最后一个分隔符word及其之后的字符全部删掉"后的字符

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    substr=${str%/*}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [http://www.kevin.com/shibo]
    

    3.2)%% 最大限度从后面截取word
    语法:${parameter%%*word},即截取 "第一个分隔符word及其之后的字符全部删掉"后的字符

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    substr=${str%%/*}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [http:]
    

    4)使用 ${var:} 模式获取子字符串
    4.1)指定从左边第几个字符开始以及子串中字符的个数
    语法:${var:start:len}

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #其中的 0 表示左边第一个字符开始,7 表示子字符的总个数。
    substr=${str:0:7}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [http://]
    

    4.2)从左边第几个字符开始一直到结束
    语法:${var:7}

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #其中的7表示左边第8个字符开始  (如果是${str:7:5},就表示从左边第8个字符开始截取,截取5个字符)
    substr=${str:7}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [www.kevin.com/shibo/anhuigrace]
    

    4.3)从右边第几个字符开始以及字符的个数
    语法:${var:0-start:len};即${var:0-8,3} 和 ${var:2-10:3} 和 ${var:5:13:3} 是一样的,即从右边第8个开始截取,截取3个字符。 即8-0=10-2=13-5=8 

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #其中的 0-23 表示右边算起第23个字符开始,5 表示字符的个数
    substr=${str:0-23:5}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [in.co]
    

    4.4)从右边第几个字符开始一直到结束
    语法:${var:0-start}

    [root@kevin~]# cat test.sh
    #!/bin/bash
    str="http://www.kevin.com/shibo/anhuigrace"
    echo "string: [${str}]"
    
    #其中的 0-6 表示右边算起第6个字符开始
    substr=${str:0-6}
    echo "substr : [${substr}]"
    
    执行结果为:
    [root@kevin~]# sh test.sh
    string: [http://www.kevin.com/shibo/anhuigrace]
    substr : [igrace]

    ####################  $( ) ${ }$(( ))的用法区别  ####################

    一、$( ) 与 ` ` (反引号) 
    ########################################################################################################################
    在Shell 中,$( ) 与 ` ` (反引号) 都是用来做命令替换用的。
    命令替换:就是完成()或反引号里的命令行,然后将其结果替换出来,再重组命令行。
    
    例如:
    [root@ss-server ~]# echo "this is $(date +%Y-%m-%d)"
    this is 2020-01-08
    [root@ss-server ~]# echo "this is `date +%Y-%m-%d`"  
    this is 2020-01-08
    
    ######  使用 $( ) 的理由 ######
    1)` ` 反引号很容易与 ' ' 单引号搞混乱;
    2)在多层次的复合替换中,` `反引号须要额外的跳脱( \` )处理,而 $( ) 则比较直观;
    
    比如命令:command1 `command2 `command3` `
    原本的意图:
    是要在 command2 `command3` 中先将 command3 提换出来给 command 2 处理,然后再将结果传给 command1 `command2 …` 来处理。
    然而,真正的结果:
    在命令行中却是分成了 `command2 ` 与 ''两段。
    
    小示例:
    使用多层次的``反引号
    [root@ss-server ~]# echo `echo `date +%Y-%m-%d``
    date +%Y-%m-%d
    
    换成 $( ) 就没问题了,做多少层的替换都没问题!
    [root@ss-server ~]# echo $(echo $(date +%Y-%m-%d))
    2020-01-08
    
    ###### $( ) 的不足 ######
    $( ) 并不见的每一种 shell类型都能使用,如果使用 bash2 的话,肯定没问题。
    
    二、${ } 用来作变量替换
    ########################################################################################################################
    一般情况下,$var 与 ${var} 并没有什么不一样。但是用 ${ } 会比较精确的界定变量名称的范围! 如下:
    [root@ss-server ~]# a=b       
    [root@ss-server ~]# echo $ab  
    
    [root@ss-server ~]# echo ${a}b
    bb
    
    原本是打算先将 $a 的结果替换出来,然后再补一个 b 字母于其后,
    但在命令行上,真正的结果却是只会提换变量名称为 ab 的值出来,结果没有ab的变量,结果就为空了!
    若使用 ${ } 就没问题。 
    
    再注意区分下面的情况:即设置变量,以 = 左边的为变量名,如以右边为变量名则无效!
    [root@ss-server ~]# a=b
    [root@ss-server ~]# echo ${b}
    
    [root@ss-server ~]# echo ${a}  
    b
    [root@ss-server ~]# echo $a b
    b b
    [root@ss-server ~]# echo ${a}${b}
    b
    [root@ss-server ~]# echo ${a}${a}
    bb
    [root@ss-server ~]# echo ${b}${b}
    
    [root@ss-server ~]# 
    
    ######################################################################
    下面开始介绍下${ } 的一些高阶功能
    
    先定义一个变量,下面示例都是以给变量做说明:
    [root@ss-server ~]# file=/dir1/dir2/dir3/my.file.txt
    
    1)可以用 ${ } 分别替换获得不同的值 ---------------------------
    使用#和%进行截取字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。
    
    ${file#*/}:  表示删除掉第一条 / 及其左边的字符串,即结果为:dir1/dir2/dir3/my.file.txt
    ${file##*/}: 表示删除掉最后一条 / 及其左边的字符串,即结果为:my.file.txt
    ${file#*.}:  表示删除掉第一个 .  及其左边的字符串,即结果为:file.txt
    ${file##*.}: 表示删除掉最后一个 .  及其左边的字符串,即结果为:txt
    ${file%/*}:  表示删除掉最后一条 / 及其右边的字符串,即结果为:/dir1/dir2/dir3
    ${file%%/*}: 表示删除掉第一条 / 及其右边的字符串,即结果为:(空值)
    ${file%.*}:  表示删除掉最后一个 .  及其右边的字符串,即结果为:/dir1/dir2/dir3/my.file
    ${file%%.*}: 表示删除掉第一个 .  及其右边的字符串,即结果为:/dir1/dir2/dir3/my
    
    关于上面使用 # 和 % 的记忆方法为:
    #  是删除掉指定字符串左边的! 
    %  是删除掉指定字符串右边的! 
    
    单一符号是最小匹配﹔两个符号是最大匹配
    #*str 是删除掉第一个str及其左边的内容; ##*str 是删除掉最后一个str及其左边的内容;
    %str* 是删除掉最后一个str及其右边的内容;%%str* 是删除掉第一个str及其右边的内容!
    
    下面的截图字符串的方法在文章上面已经详细介绍了,这里就不做过多说明了。
    ${file:0:5}:  表示提取最左边的5个字节,即结果为:/dir1
    ${file:5:10}: 表示提取第5个字节右边的连续10个字节,即结果为:/dir2/dir3
    
    如下脚本示例:
    [root@bzacbsc01ap2001 ~]# hostname 
    bzacbsc01ap2001
    
    主机名中第3到第6字符是本机的业务模块名称,也就是cbs。下面脚本中的表示从a字符串左边的第4个字符开始截取,截取3个字符(即3:3)
    [root@bzacbsc01ap2001 ~]# cat test.sh
    #!/bin/bash
    a=$(hostname)
    b=${a:3:3}
    APP=$(echo ${b})
    
    echo "本机tomcat的安装目录为: /opt/${APP}/tomcat"
    
    执行结果为:
    [root@bzacbsc01ap2001 ~]# sh test.sh 
    本机tomcat的安装目录为: /opt/cbs/tomcat
    
    2)可以使用 ${ } 对变量值里的字符串作替换 ---------------------------
    ${file/dir/path}: 表示将第一个 dir 提换为 path,即结果为:/path1/dir2/dir3/my.file.txt
    ${file//dir/path}:表示将全部 dir 提换为 path,即结果为:/path1/path2/path3/my.file.txt
    
    如下示例:
    [root@ss-server ~]# Test_Name=kevin/bo/AnHui
    [root@ss-server ~]# Test_Path=${Test_Name////.}       #使用//将变量中所有的/替换为.
    [root@ss-server ~]# echo ${Test_Path}
    kevin.bo.AnHui
    [root@ss-server ~]# Test_Path=${Test_Path/.//}        #使用/将变量中第一个.替换为/
    [root@ss-server ~]# echo ${Test_Path}
    kevin/bo.AnHui
    [root@ss-server ~]# Test_Path=$(echo $Test_Path | tr '[A-Z]' '[a-z]')
    [root@ss-server ~]# echo ${Test_Path}
    kevin/bo.anhui
    
    可以在shell脚本中进行变量的多次替换,如下:
    [root@ss-server ~]# vim test.sh
    #!/bin/bash
    MODULE_NAME=$1
    .........
    # image信息
    IMAGE_PATH=${MODULE_NAME////.}
    IMAGE_PATH=${IMAGE_PATH/.//}
    IMAGE_PATH="$IMAGE_PATH.$BRANCH.$SERVICE_NAME"
    IMAGE_PATH=$(echo $IMAGE_PATH | tr '[A-Z]' '[a-z]')
    TAG=${REVISION:0:7}
    .........
    
    3)使用 ${ } 还可以针对不同的变量状态赋值 (没设定、空值、非空值) ---------------------------
    ${file-my.file.txt}:  表示假如 $file 没有设定,则使用 my.file.txt 作传回值。(空值及非空值时不作处理) 
    ${file:-my.file.txt}: 表示假如 $file 没有设定或为空值,则使用 my.file.txt 作传回值。 (非空值时不作处理)
    ${file+my.file.txt}:  表示假如 $file 设为空值或非空值,均使用 my.file.txt 作传回值。(没设定时不作处理)
    ${file:+my.file.txt}: 表示假如 $file 为非空值,则使用 my.file.txt 作传回值。 (没设定及空值时不作处理)
    ${file=my.file.txt}:  表示假如 $file 没设定,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (空值及非空值时不作处理)
    ${file:=my.file.txt}: 表示假如 $file 没设定或为空值,则使用 my.file.txt 作传回值,同时将 $file 赋值为 my.file.txt 。 (非空值时不作处理)
    ${file?my.file.txt}:  表示假如 $file 没设定,则将 my.file.txt 输出至 STDERR。 (空值及非空值时不作处理)
    ${file:?my.file.txt}: 表示假如 $file 没设定或为空值,则将 my.file.txt 输出至 STDERR。 (非空值时不作处理)
    
    ${1:-NULL}   表示是当$1为空时,自动将NULL替换成$1所要带入的变量值。
    ${2:-NULL}   表示是当$2为空时,自动将NULL替换成$2所要带入的变量值。
    
    例如:
    [root@ss-server ~]# kevin=123
    [root@ss-server ~]# echo ${kevin+anhui}                
    anhui
    
    [root@ss-server ~]# echo ${haha:=null}    #haha变量没有设定,则使用=后面的null作为传回值         
    null
    
    也可以在shell脚本中进行变量的状态赋值
    [root@ss-server ~]# vim test.sh
    #!/bin/bash
    .........
    AFS_ENV=${AFS_ENV:=null}
    AFS_APPID=${AFS_APPID:=null}
    AFS_CLUSTER=${AFS_CLUSTER:=null}
    AFS_JARNAME=${AFS_JARNAME:=null}
    .........
    
    对于上面的理解,在于一定要分清楚 unset 与 null 及 non-null 这三种赋值状态。
    一般而言, : 与 null 有关, 若不带 : 的话, null 不受影响, 若带 : 则连 null 也受影响!
    [root@ss-server ~]# kevin=123           
    [root@ss-server ~]# echo ${kevin:+anhui} 
    anhui
    [root@ss-server ~]# kevin=
    [root@ss-server ~]# echo ${kevin:+anhui} 
    
    [root@ss-server ~]# unset kevin
    [root@ss-server ~]# echo ${kevin:+anhui} 
    
    [root@ss-server ~]#
    
    使用${#var}可以计算出变量的长度
    [root@ss-server ~]# echo ${file}
    /dir1/dir2/dir3/my.file.txt
    [root@ss-server ~]# echo ${#file}
    27
    
    三、bash的组数(array)处理方法
    ########################################################################################################################
    一般而言,A="be sh se cho" 这样的变量只是将 $A 替换为一个单一的字符串,
    但是改为 A=(be sh se cho) ,则是将 $A 定义为组数,所以说数组定义需要使用()括号!!
    
    关于数组的使用,之前已经在 https://www.cnblogs.com/kevingrace/p/5761975.html 这篇文章中详细介绍了,这里简略说下:
    
    组数常用的几个替换方法:
    ${A[@]} 或 ${A[*]}       表示获得全部组数,即得到be sh se cho 。
    ${A[0]}                  表示获得数组中的第1个组数。同理,${A[1]} 获得的是第2个组数。
    ${#A[@]} 或 ${#A[*]}     表示获得全部组数数量。
    ${#A[0]}                 表示获得第一个组数的长度,即be的长度,为2; 同理,${#A[3]} 表示获得第四个组数的长度,即cho的长度,为3;
    A[1]=haha                 表示将第2个组数重新定义为haha; 同理,A[3]=heihei 表示将第4个组数重新定义为heihei;
    
    四、$(( )) 用途:用来作整数运算
    ########################################################################################################################
    在 bash 中,$(( )) 的整数运算符号大致有这些:
    + - * /    分别表示为 "加、减、乘、除"。
    %          表示余数运算
    & | ^ !    分别表示分别为 "AND、OR、XOR、NOT" 运算。
    
    例如:
    [root@ss-server ~]# a=6;b=7;c=8
    [root@ss-server ~]# echo $(( a+b*c ))
    62
    [root@ss-server ~]# echo $(( (a+b+3)/c )) 
    2
    [root@ss-server ~]# echo $(( (a*b)%c))
    2
    
    使用$[]、let、$(()) 都可以作为整数运算,效果是一样的!
    [root@ss-server ~]# echo $((4*9))
    36
    [root@ss-server ~]# echo $[4*9]
    36
    [root@ss-server ~]# let a=4*9
    [root@ss-server ~]# echo $a 
    36
    [root@ss-server ~]# let "a=4*9"
    [root@ss-server ~]# echo $a    
    36
    [root@ss-server ~]# let a="3+5"   
    [root@ss-server ~]# echo $a       
    8
    [root@ss-server ~]# a=18
    [root@ss-server ~]# let a++   
    [root@ss-server ~]# echo $a   
    19
    
    事实上,单纯用 (( )) 也可重定义变量值。
    (( )) 这组符号的作用与 let 指令相似,用在算数运算上,是 bash 的内建功能。所以,在执行效率上会比使用 let指令要好许多。
    [root@ss-server ~]# a=10; ((a++)) 
    [root@ss-server ~]# echo ${a}
    11
    
    [root@ss-server ~]# cat test.sh
    #!/bin/bash
    (( a = 10 ))
    echo -e "inital value, a = $a
    "
     
    (( a++))
    echo "after a++, a = $a"
     
    [root@ss-server ~]# sh test.sh
    inital value, a = 10
     
    after a++, a = 11
    
    更多内容,可参考另一篇文章的总结: https://www.cnblogs.com/kevingrace/p/5896386.html
  • 相关阅读:
    [转]利用docker进行java开发小demo
    markdown简介及语法
    Thinking in Java 之classpath理解
    docker官方windows安装
    Thinking in Java笔记之类及对象的初始化
    开发工具之play framework
    图解phpstorm常用快捷键
    Git相关
    Yii 1.1 cookie删不掉
    ajax跨域,这应该是最全的解决方案了
  • 原文地址:https://www.cnblogs.com/kevingrace/p/8868262.html
Copyright © 2011-2022 走看看