Liunx的shell编程中,字符串的处理可以说是最常见的操作了,下面跟我从浅到深一起来看看字符串操作有哪些道道:
字符串表示
有三种表示方法:
- 直接声明,字符串内容中不能出现空格:
firstStr=对不起我是产品经理
出现变量时,变量会被解析成自身的值:
firstStr=对不起我是产品经理secondStr=换个角度跟$firstStr理解Shell编程echo $secondStr
运行结果是:
换个角度跟对不起我是产品经理理解Shell编程
- 单引号声明,引号中所有内容保持原样,字符串内容可以出现空格:
firstStr=对不起我是产品经理secondStr='换个角度跟 $firstStr 理解Shell编程'echo $secondStr
运行结果是:
换个角度跟 $firstStr 理解Shell编程
- 双引号声明,字符串内容中能出现空格,但变量将被解析,如字符串中有双引号,则需要加转义符:
firstStr=对不起我是产品经理secondStr="换个角度跟 "$firstStr" 理解Shell编程"echo $secondStr
运行结果是:
换个角度跟 "对不起我是产品经理" 理解Shell编程
字符串连接
通过上面对字符串声明的定义,可以知道连接两个字符串有以下方法:
thirdStr=$firstStr$secondStrthirdStr="$firstStr$secondStr"
有个特殊一点的情况是变量出现在其它字符串中,需要使用大括号来标记变量名称边界:
thirdStr="I am not${firstStr}a product ${secondStr}manager."
Tips: 获取字符串的长度:
originStr="I have 1024 programmer working for me."echo ${#originStr}
运行结果:
38
向右/左截取字符串(原生)
- 按从左向右的位置index(从0开始计数)向右截取长度len的子串
${originalStr: index :len}
例如:
originalStr="Sorry,I am PM"echo ${originalStr: 6: 8}
运行结果是:
I am PM
如果省略len,则截取到字符串尾:
originalStr="Sorry,I am PM.You are not"echo ${originalStr: 6}
运行结果是:
I am PM.You are not
- 按从右向左的位置index(从1开始计数)向右截取长度len的子串
${originalStr: 0-index :len}
例如:
originalStr="Sorry,I am PM"echo ${originalStr: 0-7: 8}
运行结果是:
I am PM
如果省略len,则截取到字符串尾:
originalStr="Sorry,I am PM.You are not"echo ${originalStr: 0-7}
运行结果是:
I am PM.You are not
- 从指定的子串(不包含这个子串)开始向右截取,*表示任意一个或多个字符,?表示任意单个字符
${originalStr#*subStr}
例如:
originalStr="Sorry,I am PM.You are not"echo ${originalStr#*,}
运行结果:
I am PM.You are not
使用#意为匹配第一个出现的子串,使用##意为匹配最后一个出现的子串
例如:
originalStr="Sorry,I am PM.You are not"echo ${originalStr#*r}echo ${originalStr##*r}
运行结果:
ry,I am PM.You are note not
需要精确匹配从开头对其的子串时,可以不用*,比如:
originalStr="Sorry,I am PM.You are not"echo ${originalStr#Sorry}echo ${originalStr#orry}
运行结果:
,I am PM.You are notSorry,I am PM.You are not
使用?进行匹配的时候类似
originalStr="Sorry,I am PM.You are not"echo ${originalStr#So??y}
运行结果:
,I am PM.You are not
- 从指定的子串(不包含这个子串)开始向左截取,*表示任意一个或多个字符,?表示任意单个字符
与上面类似,将使用的运算符#改为%,通配符放在子串的右面,这里就不再赘述。
截取字符串(使用cut)
基本用法一:按字符或字节截取数字表示范围的字符
echo $originStr | cut -c/-b numOrRange
例如:
originalStr="Sorry,I am PM.You are not"echo $originalStr | cut -c1-5
运行结果:
Sorry
-c是以字符为单位,-b是以字节为单位,在英文字符串的情境下没有区别,中文的情况以后讨论。
基本用法二:按域分隔符截取数字序号的域
echo $originStr | cut -d delimiter -f fieldNum
-d是标记域分隔符号的,例如:
originalStr="Sorry:I:am:PM:You:are:not"echo $originalStr | cut -d ':' -f1
运行结果:
Sorry
可以选取多个域,但是同时会输出域分隔符,如果想替换域分隔符的话,需要使用--output-delimiter参数将分隔符替换为制表符或者空格
例如:
originalStr="Sorry:I:am:PM:You:are:not"echo $originalStr | cut -d ':' -f1,4 --output-delimiter=" "
运行结果:
Sorry PM
另外,numOrRange还有-3,3-,3-5,等玩法,留给大家自己玩一下
字符串按域截取(使用awk)
基本用法:
echo $originalStr | awk '{print firstColNum "" secondColNum ""……}'
例子:
originalStr="Sorry I am PM You are not"echo $originalStr | awk '{print $1 "" $4 ""}'
运行结果:
SorryPM
如果分隔符与上面的例子一样用的是:,则需要加一个子句BEGIN{FS=":"}
originalStr="Sorry:I:am:PM:You:are:not"echo $originalStr | awk 'BEGIN{FS=":"}{print $1 "" $4 ""}'
运行结果:
SorryPM
字符串去重、大小写转换、删除、替换(使用tr)
基本用法:tr [–c/d/s/t] [firstCharSet] [secondCharSet]
-c 使用secondCharSet的字符补全firstCharSet不包含的字符
-d 删除firstCharSet包含的字符
-s 压缩firstCharSet包含的字符
-t 使用secondCharSet替换对应的firstCharSet里包含的字符(默认参数)
- 去重:
例:
echo IIIIaaaammmmPPPPMMMM | tr -s [a-z]
运行结果:
IIIIamPPPPMMMM
注:如果压缩全部大小写字母,要使用[A-z]
- 大小写转换:
例:
echo I AM PM | tr [A-Z] [a-z]
运行结果:
i am pm
一些扩展的字符集定义如下:
- 删除指定的字符:
例:(删除字符串中的M和空格)
echo "I AM PM" |tr -d "[M] [ ]"
运行结果:
IAP
- 批量替换字符集之外的字符:
例:
echo "I have 1024 programmers working for me."|tr -sc "[a-z][A-Z][ ]" " "
运行结果:
I have programmers working for me
总结一下:这篇文章除了字符串定义、连接等基础知识外,主要讲了按位置进行截取左右半截字符串(原生#%)、按位置截取任意位置任意长度字符串(cut)、按域分隔符截取字符串(cut、awk),以及字符串的去重、大小写转换、删除、替换(使用tr)。
字符串操作还有很多其它的命令可以用,但常见的也就这几种了,如果你觉得有用的话,多加练习,一定可以熟练掌握。
我将陆续归纳shell编程的一些难点重点,欢迎关注我获取更多动态。
本文为作者心血原创,禁止任何方式转载抄袭。