Shell脚本字符串匹配及⽇常命令⼯具-⽤法总结(技巧指南)
Shell提供了很多字符串和⽂件处理的命令,如awk、expr、grep、sed等命令,还有⽂件的排序、合并和分割等⼀系列的操作命令。下⾯重点总结下Shell字符串处理、⽂本处理以及各类命令及函数⽤法。
先从expr命令开始梳理,expr 引出通⽤求值表达式,可以实现算术操作、⽐较操作、字符串操作和逻辑操作等功能。
1) 计算字符串长度
字符串名为string,可以使⽤命令 ${#string} 或 expr length ${string} 两种⽅法来计算字符串的长度。
若string中包括空格,则expr计算命令中需⽤双引号引起来,即expr length "${string}"。(${#string}⽅法对于有⽆空格的字符串均可使⽤)
需要注意:expr length后⾯只能跟⼀个参数,string有空格会当作多个参数处理。
[root@kevin ~]# string="kevinisgood"
[root@kevin ~]# expr length ${string}
11
[root@kevin ~]# expr length "${string}"
11
[root@kevin ~]# echo ${#string}                  # 使⽤⾃带shell函数读取字符串长度
11
如果string字符串中有空格
[root@kevin ~]# string="kevin is good"
[root@kevin ~]# expr length ${string}
expr: syntax error
[root@kevin ~]# expr length "${string}"
13
[root@kevin ~]# echo ${#string}
13
注意:这⾥说到如果string字符串中有空格,则需要双引号引起来。但如果是单引号引起来呢?
如果string字符串⽤单引号引起来,则统计出来的是"字符串去重和去掉空格"后的长度
[root@kevin ~]# echo ${string}
kevin is good
[root@kevin ~]# expr length '${string}'        #使⽤单引号的话,统计的是"字符去重以及去掉空格"之后的长度
9
[root@kevin ~]# string="kevinisgood"
[root@kevin ~]# echo ${string}
kevinisgood
[root@kevin ~]# expr length '${string}'
9
2)匹配字符串长度
即匹配字符串开头⼦串的长度!!使⽤命令 expr match ${string} $substring,表⽰在string字符串的开头匹配substring字符串,返回匹配到的substring字符串的长度。若string 开头匹配不到则返回0,其中substring可以是字符串也可以是正则表达式。
expr匹配字符串长度的两种格式:
# expr match "$string" '$substring'
# expr "$string" : '$substring'
[root@kevin ~]# string="zhongguo hao"
[root@kevin ~]# expr length "${string}"
12
[root@kevin ~]# expr match "${string}" "z.*"
12
[root@kevin ~]# expr match "${string}" "zho"
3
[root@kevin ~]# expr match "${string}" "hao"
注意:
"hao"尽管在string字符串中出现,但是未出现在string的开头处,因此返回0!
所以说,expr match匹配的⼀定是字符串开头⼦串的长度!!
后⾯的$substring可以是正则, $substring两边是单引号或双引号⽆所谓。
[root@kevin ~]# string="KEvin IS good"
[root@kevin ~]# expr match "${string}" "[A-Z]*"
2
[root@kevin ~]# expr match "${string}" '[A-Z]*'
2
[root@kevin ~]# expr "${string}" : "[A-Z]*"      #注意这种⽅法中就没有了"match"参数
2
[root@kevin ~]# expr "${string}" : '[A-Z]*[a-z]*'
5
3)匹配字符串索引
expr的索引命令格式为:expr index ${string} $substring。
在字符串$string上匹配$substring中字符最早第⼀次出现的位置(从左到右,从1开始),匹配不到,expr index返回0。
简单来说,就是出⼦串在字符串中最早第⼀次出现的单个字符的位置!!
[root@kevin ~]# string="love beijing"
[root@kevin ~]# echo ${string}
love beijing
[root@kevin ~]# expr index ${string} "bei"
expr: syntax error
[root@kevin ~]# expr index "${string}" "bei"        #注意string字符串中有空格,需要加双引号
4
[root@kevin ~]# expr index "${string}" "jing"
8
[root@kevin ~]# expr index "${string}" "haa"
注意:
expr index命令中返回的是后⾯$substring中"⼦串字符中"最早第⼀次出现的位置。
"jing"⼦串中在${string}字符串中最早第⼀次出现的是"i",第4位置
"haa"匹配不到,所以返回0!
===  Bash Shell命令  ===
4)抽取字符串的⼦串
Shell提供两种命令和expr实现抽取⼦串功能。
正着抽取(即从左到右)有两种格式。(左边默认从0开始标号)
格式⼀:{string:position}  从名称为${string}的字符串的第$position个位置开始抽取⼦串,从0开始标号。
格式⼆:{string:position:length}  增加$length变量,表⽰从${string}字符串的第$position个位置开始抽取长度为$length的⼦串。
需要注意:都是从string的左边开始计数抽取⼦串。
⽰例:
[root@kevin ~]# string="hello world wang"
[root@kevin ~]# echo ${string}
hello world wang
[root@kevin ~]# echo ${string:0}    #从标号为0(即从第⼀个字母)开始截取,截取到结尾。
hello world wang
[root@kevin ~]# echo ${string:6}    #从标号为6的字符开始截取,截取到结尾。
world wang
[root@kevin ~]# echo ${string:6:4}  #从标号为6的字符开始截取,截取长度为4。
worl
[root@kevin ~]# echo ${string:6:0}  #从标号为6的字符开始截取,截取长度为0。
[root@kevin ~]#
反着抽取(即从右到左)有两种格式。(右边默认从-1开始标号)
格式⼀:{string: -position}。需要谨记:冒号与横杠间有⼀个空格
格式⼆:{string:(position)}。如果加了括号,则冒号后⾯加不加空格是⼀样的效果
[root@kevin ~]# echo ${string:-2}    #冒号与"-"之间必要要有空格,否则截取⽆效!
hello world wang
[root@kevin ~]# echo ${string: -2}
ng
[root@kevin ~]# echo ${string:(-2)}
ng
[root@kevin ~]# echo ${string: (-2)}
ng
如果要想实现从右边第⼏个字符开始截取,截取长度为多少,则⽅法为:
{string:m-n:x} 表⽰从右边第"m-n"个字符开始截取,截取长度为x
[root@kevin ~]# echo ${string:1-7:3}
d w
[root@kevin ~]# echo ${string:3-9:3}
d w
expr substr也能够实现抽取⼦串功能,命令格式:expr substr ${string} $position $length,
这个与上⾯最⼤不同是expr substr命令从1开始进⾏标号
[root@kevin ~]# echo ${string}
hello world wang
[root@kevin ~]# echo ${string:3:5}            #从0开始进⾏标号
lo wo
[root@kevin ~]# expr substr "${string}" 3 5  #从1开始标号
llo w
还可以使⽤正则表达式抽取⼦串的命令,但只能抽取string开头处或结尾处的⼦串。
抽取字符串开头处的⼦串:
格式⼀:expr match $string ''
格式⼆:expr $string : ''。注意:其中冒号前后都有⼀个空格。
抽取字符串结尾处的⼦串:
格式⼀:expr match $string '.*'
格式⼆:expr $string : '.*'。注意:.*表⽰任意字符的任意重复。⼀个.表⽰⼀个字符。
[root@kevin ~]# string="20181112hello WORld Good"
[root@kevin ~]# echo ${string}
20181112hello WORld Good
[root@kevin ~]# expr match "$string" '\([0-9]*\)'    #这⾥的${string}最好使⽤双引号引起来,因为字符串可能中有空格!如果没有空格,就可以不⽤使⽤双引号。20181112
[root@kevin ~]# expr match "$string" "\([0-9]*\)"
20181112
[root@kevin ~]# expr "$string" : '\([0-9]*\)'
20181112
[root@kevin ~]# expr match "$string" '.*\(.\)'
d
[root@kevin ~]# expr match "$string" '.*\(..\)'
od
[root@kevin ~]# expr match "$string" '.*\(...\)'
ood
[root@kevin ~]# expr match "$string" '.*\(.....\)'
Good
[root@kevin ~]# expr "$string" : '.*\(.....\)'
Good
[root@kevin ~]# expr "$string" : '.*\(.........\)'
ORld Good
[root@kevin ~]# string="heLLO2018 world"
[root@kevin ~]# expr match "$string" '\([a-z]*\)'
he
[root@kevin ~]# expr match "$string" '\([a-Z]*\)'
正则匹配中配到到带单引号
heLLO
[root@kevin ~]# expr match "$string" '\([a-Z]*[0-9]*\)'
heLLO2018
[root@kevin ~]# expr match "$string" '\(.[a-Z]*[0-9]*\)'
heLLO2018
[root@kevin ~]# expr "$string" : '.*\(.........\)'
018 world
5)删除字符串的⼦串
删除字串是指将原字符串中符合条件的⼦串删除。
从string开头处删除⼦串:
格式⼀:${string#substring}    删除开头处与substring匹配的最短⼦串。
格式⼆:${string##substring}  删除开头处与substring匹配的最长⼦串。其中substring并⾮是正则表达式⽽是通配符。
[root@kevin ~]# string="china IS niuBIlity2018"
[root@kevin ~]# echo ${string#c*i}    #删除c开头到a的最短⼦串
na IS niuBIlity2018
[root@kevin ~]# echo ${string##c*i}    #删除c开头到a的最长⼦串
ty2018
[root@kevin ~]# echo ${string#c*n}
a IS niuBIlity2018
[root@kevin ~]# echo ${string##c*n}
iuBIlity2018
[root@kevin ~]# echo ${string#ch*n}    #删除ch开头到a的最短⼦串
a IS niuBIlity2018
[root@kevin ~]# echo ${string##ch*n}  #删除ch开头到a的最长⼦串
iuBIlity2018
上⾯#或##后⾯的字符必须是${string}字符串的开头⼦串!否则删除⼦串就⽆效了!
[root@kevin ~]# echo ${string#i*n}    #i不是开头字符,所以删除⽆效
china IS niuBIlity2018
[root@kevin ~]# echo ${string##i*n}  #i不是开头字符,所以删除⽆效
china IS niuBIlity2018
另外:可以使⽤下⾯⽅式进⾏删除:
${string#*substring}    删除${string}字符串中第⼀个$substring及其之前的字符
${string##*substring}    删除${string}字符串中最后⼀个$substring及其之前的字符
[root@kevin ~]# string="china IS niuBIlity2018"
[root@kevin ~]# echo ${string#*i}    #删除第⼀个i及其之前的字符
na IS niuBIlity2018
[root@kevin ~]# echo ${string##*i}  #删除最后⼀个i及其之前的字符
ty2018
也可以使⽤下⾯⽅法进⾏删除
格式⼀:${string%substring*}    删除${string}字符串中最后⼀个$substring及其之后的字符
格式⼆:${string%%substring*}  删除${string}字符串中第⼀个$substring及其之后的字符
[root@kevin ~]# echo ${string}
china IS niuBIlity2018
[root@kevin ~]# echo ${string%i*}
china IS niuBIl
[root@kevin ~]# echo ${string%%i*}
ch
[root@kevin ~]# echo ${string%c*}
[root@kevin ~]# echo ${string%%c*}
[root@kevin ~]#
6)字符串替换
替换⼦串命令可以在任意处、开头处、结尾处替换满⾜条件的⼦串,其中的substring都不是正则表达式⽽是通配符。
在任意处替换⼦串命令:
格式⼀:${string/substring/replacement},仅替换第⼀次与substring相匹配的⼦串。
格式⼆:${string//substring/replacement},替换所有与substring相匹配的⼦串。
[root@kevin ~]# string="china IS niuBIlity2018"
[root@kevin ~]# echo ${string/i/#}
ch#na IS niuBIlity2018
[root@kevin ~]# echo ${string//i/#}
ch#na IS n#uBIl#ty2018
[root@kevin ~]# echo ${string}
china IS niuBIlity2018
[root@kevin ~]# echo ${string/ /--}  #替换空格
china--IS niuBIlity2018
[root@kevin ~]# echo ${string// /--}
china--IS--niuBIlity2018
在开头处替换与substring相匹配的⼦串,格式为:${string/#substring/replacement}。
在结尾除替换与substring相匹配的⼦串,格式为:${string/%substring/replacement}。
[root@kevin ~]# echo ${string}
china IS niuBIlity2018
[root@kevin ~]# echo ${string/#ch/he}
heina IS niuBIlity2018
[root@kevin ~]# echo ${string/#china/anhui}
anhui IS niuBIlity2018
[root@kevin ~]# echo ${string/#niu/he}    #注意这⾥#后⾯的字符必须是${string}字符串中开头的字符
china IS niuBIlity2018
[root@kevin ~]# echo ${string/%2018/2020}
china IS niuBIlity2020
[root@kevin ~]# echo ${string/%lity2018/hehehe}
china IS niuBIhehehe
7)${!varprefix*} 和 ${!varprefix@}
[root@kevin ~]# test="bobo"
[root@kevin ~]# test1="bobo1"
[root@kevin ~]# test2="bobo2"
[root@kevin ~]# test4="bobo4"
[root@kevin ~]# echo ${!test*}
test test1 test2 test4
[root@kevin ~]# echo ${!test@}
test test1 test2 test4
8)参数替换
从string开头处删除⼦串:
格式⼀:${string#substring}    删除开头处与substring匹配的最短⼦串。
格式⼆:${string##substring}  删除开头处与substring匹配的最长⼦串。其中substring并⾮是正则表达式⽽是通配符。
[root@kevin ~]# echo ${string#c*i}    #删除c开头到a的最短⼦串
na IS niuBIlity2018
[root@kevin ~]# echo ${string##c*i}    #删除c开头到a的最长⼦串
ty2018
[root@kevin ~]# echo ${string#c*n}
a IS niuBIlity2018
[root@kevin ~]# echo ${string##c*n}
iuBIlity2018
[root@kevin ~]# echo ${string#ch*n}    #删除ch开头到a的最短⼦串
a IS niuBIlity2018
[root@kevin ~]# echo ${string##ch*n}  #删除ch开头到a的最长⼦串
iuBIlity2018
上⾯#或##后⾯的字符必须是${string}字符串的开头⼦串!否则删除⼦串就⽆效了!
[root@kevin ~]# echo ${string#i*n}    #i不是开头字符,所以删除⽆效
china IS niuBIlity2018
[root@kevin ~]# echo ${string##i*n}  #i不是开头字符,所以删除⽆效
china IS niuBIlity2018
另外:可以使⽤下⾯⽅式进⾏删除:
${string#*substring}    删除${string}字符串中第⼀个$substring及其之前的字符
${string##*substring}    删除${string}字符串中最后⼀个$substring及其之前的字符
[root@kevin ~]# string="china IS niuBIlity2018"
[root@kevin ~]# echo ${string#*i}    #删除第⼀个i及其之前的字符
na IS niuBIlity2018
[root@kevin ~]# echo ${string##*i}  #删除最后⼀个i及其之前的字符
ty2018
也可以使⽤下⾯⽅法进⾏删除
格式⼀:${string%substring*}    删除${string}字符串中最后⼀个$substring及其之后的字符
格式⼆:${string%%substring*}  删除${string}字符串中第⼀个$substring及其之后的字符
[root@kevin ~]# echo ${string}
china IS niuBIlity2018
[root@kevin ~]# echo ${string%i*}
china IS niuBIl
[root@kevin ~]# echo ${string%%i*}
ch
[root@kevin ~]# echo ${string%c*}
[root@kevin ~]# echo ${string%%c*}
[root@kevin ~]#
-------------------------------------------------------------------
再看下⾯⼀例:
[root@kevin ~]# str=bo/www/kevin/data/test/ccd.log
[root@kevin ~]# echo ${str#*/*/}
kevin/data/test/ccd.log
[root@kevin ~]# echo ${str##*/*/}
ccd.log
[root@kevin ~]# echo ${str%/*/*}
bo/www/kevin/data
[root@kevin ~]# echo ${str%%/*/*}
bo
以上是以/*/作为匹配的字符串,即正则匹配的字符串。
9)如何判断⼀个字符串是否由字母数字开头(grep)
1)判断⼀个字符串是否由⼤⼩写字母或数字开头(或结尾)
[root@kevin ~]# cat test.sh
#!/bin/bash
#str="This IS a root USER, 20171aaabb"
read -p "请输⼊内容:" str
if echo "${str}" | grep -q '^[A-Za-z0-9].*\+$'; then
echo -e "${str}\nok"
else
echo "invaliad"
fi
需要注意:
脚本中的echo后⾯只需要添加-e参数,是为了让打印中的\n换⾏符⽣效!如果不加-e参数,则\n就被做当普通字符打印出来了!read -p 表⽰"指定要显⽰的提⽰"。如果添加-s参数,即"read -sp",则表⽰"静默输⼊,即隐藏输⼊的数据,⼀般⽤于密码输⼊"执⾏脚本:
[root@kevin ~]# sh test.sh
请输⼊内容:TOOk213gg
TOOk213gg
ok
[root@kevin ~]# sh test.sh
请输⼊内容:@#sadf123
invaliad
[root@VM_16_9_centos ~]# sh test.sh
请输⼊内容:arTR213#$1
arTR213#$1
ok
==============================================================
[root@kevin ~]# read -p "输⼊你想要输⼊的内容:"
输⼊你想要输⼊的内容:asdfsafsaf
[root@kevin ~]# read -sp "输⼊你想要输⼊的内容:"  #加了-s参数后,即为静默输⼊,隐藏输⼊的内容
输⼊你想要输⼊的内容:
[root@kevin ~]#
==============================================================
为了简化,还可以将上⾯脚本中的:
grep -q '^[A-Za-z0-9].*\+$'
grep -q '^[A-Za-z0-9].*'
--------------------------------------
如果判断⼀个字符串是否由⼤⼩写字母或数字结尾则只需要将上⾯脚本中的:grep -q '^[A-Za-z0-9].*\+$'
改为
grep -q '.*[A-Za-z0-9]$'
==============================================================还要注意:
'^[A-Za-z0-9].*\+$'  表⽰以⼤写字母或⼩写字母或数字为开头。没有顺序要求!!
'^[A-Za-z0-9].*'    可以直接去掉后⾯的"\+$"部分
'^[A-Z].*'          表⽰以⼤写字母开头
'^[a-z].*'          表⽰以⼩写字母开头
'^[0-9].*'          表⽰以数字字母开头
下⾯都是最常⽤的
grep ^[0-9]
grep "^[0-9]"
grep ^[a-z]
grep "^[a-z]"
grep ^[A-Z]
grep "^[A-Z]"
grep ^[a-Z]
grep "^[a-Z]"
grep .*[0-9]$
grep ".*[0-9]$"
grep ".*[a-z]$"
grep ".*[a-z]$"
grep ".*[A-Z]$"
grep ".*[A-Z]$"
grep .*[a-Z]$
grep ".*[a-Z]$"
grep [0-9]G
grep [a-z]2018_data
[root@kevin ~]#
Good study 2018! hahahah~
good Study 2018hehehehe
2018 Good study 1wqe
2018stuDY is heht6ttt
!@#asdf
TOOk213gg asdfasdf
anhui 2018asdfjlsadfdsaff
#$$$$$
[root@kevin ~]# ep '^[A-Z].*\+$'
Good study 2018! hahahah~
TOOk213gg asdfasdf
[root@kevin ~]# ep '^[a-z].*\+$'
good Study 2018hehehehe
anhui 2018asdfjlsadfdsaff
[root@kevin ~]# ep '^[0-9].*\+$'
2018 Good study 1wqe
2018stuDY is heht6ttt
[root@kevin ~]# ep '^[A-Za-z0-9].*\+$'
Good study 2018! hahahah~
good Study 2018hehehehe
2018 Good study 1wqe
2018stuDY is heht6ttt
TOOk213gg asdfasdf
anhui 2018asdfjlsadfdsaff
[root@kevin ~]# ep -v '^[A-Za-z0-9].*\+$'
!@#asdf
#$$$$$
[root@kevin ~]# ep -v '^[A-Z].*\+$'|grep -v '^[a-z].*\+$'|grep -v '^[0-9].*\+$'  !@#asdf
#$$$$$
[root@kevin ~]# |grep -v ^[a-Z]
2018 Good study 1wqe
2018stuDY is heht6ttt
!@#asdf
#$$$$$
[root@kevin ~]# |grep -v ^[a-Z]|grep -v [0-9]
!
@#asdf
#$$$$$
grep获取多个条件(grep -E "条件1|条件2|条件3")
[root@kevin ~]# |grep -E "^[a-z]|^[0-9]"
good Study 2018hehehehe
2018 Good study 1wqe
2018stuDY is heht6ttt
anhui 2018asdfjlsadfdsaff
grep过滤多个条件(grep -v "条件1\|条件2\|条件3"),注意""⾥⾯有转义符"\"
[root@kevin ~]# |grep -v "^[a-z]\|^[0-9]"
Good study 2018! hahahah~
!
@#asdf
TOOk213gg asdfasdf
#$$$$$
[root@kevin ~]# |grep -v "[a-z]\|^[0-9]"

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。