您好,欢迎访问三七文档
当前位置:首页 > 商业/管理/HR > 管理学资料 > shell编程范例之字符串操作
shell编程范例之字符串操作忙活了一个礼拜,终于等到周末,可以空下来写点东西。这次介绍_字符串操作_了,这里先得明白两个东西,什么是字符串,对字符串有哪些操作?下面是在线新华字典的解释:字符串:简称“串”。有限字符的序列。数据元素为字符的线性表,是一种数据的逻辑结构。在计算机中可有不同的存储结构。在串上可进行求子串、插入字符、删除字符、置换字符等运算。而字符呢?字符:计算机程序设计及操作时使用的符号。包括字母、数字、空格符、提示符及各种专用字符等。照这样说,之前介绍的数值操作中的数字,逻辑运算中的真假值,都是以字符的形式呈现出来的,是一种特别的字符,对它们的运算只不过是字符操作的特例罢了。而这里将研究一般字符的运算,它具有非常重要的意义,因为对我们来说,一般的工作都是处理字符而已。这些运算实际上将围绕上述两个定义来做。第一、找出字符或者字符串的类型,是数字、字母还是其他特定字符,是可打印字符,还是不可打印字符(一些控制字符)。第二、找出组成字符串的字符个数和字符串的存储结构(比如数组)。第三、对串的常规操作:求子串、插入字符、删除字符、置换字符、字符串的比较等。第四、对串的一些比较复杂而有趣的操作,这里将在昀后介绍一些有趣的范例。1.字符串的属性1.1字符串的类型字符有可能是数字、字母、空格、其他特殊字符,而字符串有可能是它们任何一种或者多种的组合,在组合之后还可能形成一个具有特定意义的字符串,诸如邮件地址,URL地址等。概要示例:下面我们来看看如何判断字符的类型。//数字或者数字组合(能够返回结果,即程序退出状态是0,说明属于这种类型,反之不然)$i=5;j=9423483247234;$echo$i|grep[0-9]*5$echo$j|grep[0-9]*9423483247234$echo$j|grep[0-9]*/dev/null$echo$?0//字符组合(小写字母、大写字母、两者的组合)$c=A;d=fwefewjuew;e=fewfEFWefwefe$echo$c|grep[A-Z]A$echo$d|grep[a-z]*fwefewjuew$echo$e|grep[a-zA-Z]*fewfEFWefwefe//字母和数字的组合$ic=432fwfwefeFWEwefwef$echo$ic|grep[0-9a-zA-Z]*432fwfwefeFWEwefwef//空格或者Tab键等$echo|grep$echo-e\t|grep[[:space:]]#[[:space:]]会同时匹配空格和TAB键$echo-e\t|grep[[:space:]]$echo-e\t|greptab#tab为在键盘上按下TAB键,而不是字符tab//匹配邮件地址$echotest2007@lzu.cn|grep[0-9a-zA-Z\.]*@[0-9a-zA-Z\.]test2007@lzu.cn//匹配URL地址(以http链接为例)$echo=10135|grephttp://[0-9a-zA-Z\./=?]*=10135说明:[1]/dev/null和/dev/zero是非常有趣的两个设备,它们都犹如一个黑洞,什么东西掉进去都会消失殆尽;后者则是一个能源箱,你总能从那里取到0,直到你退出。两者的部分用法见:关于zero及NULL设备的一些问题[2][[:space:]]是grep用于匹配空格或者TAB键类型字符串的一种标记,其他类似的标记请查看grep的帮助,mangrep。[3]上面都是用grep来进行模式匹配,实际上sed,awk都可以用来做模式匹配,关于匹配中用到的正则匹配模式知识,大家可以参考正则匹配模式,更多相关资料请看参考资料。[4]如果仅仅想判断字符串是否为空,即判断字符串的长度是否为零,那么可以简单的通过test命令的-z选项来判断,具体用法见test命令,mantest.概要示例:判断字符是否可打印?如何控制字符在终端的显示。//用grep判断某个字符是否为可打印字符$echo\t\n|grep[[:print:]]\t\n$echo$?0$echo-e\t\n|grep[[:print:]]$echo$?1//用echo的-e选项在屏幕控制字符显示位置、颜色、背景等$echo-e\33[31;40m#设置前景色为黑色,背景色为红色$echo-e\33[11;29HHello,World\!#在屏幕的第11行,29列开始打印字符串Hello,World!//在屏幕的某个位置动态显示当前系统时间$while:;doecho-e\33[11;29H$(date+%Y-%m-%d%H:%M:%S);done//用col命令过滤掉某些控制字符,在处理诸如script,screen等截屏命令的输出结果时,很有用$screen-L$cat/bin/cat$exit$catscreenlog.0|col-b#把一些控制字符过滤后,就可以保留可读的操作日志更多关于字符在终端的显示控制方法,请参考资料[20]和字符显示实例[21]:用shell实现的一个动态时钟。1.2字符串的长度概要示例:除了组成字符串的字符类型外,字符串还有哪些属性呢?组成字符串的字符个数。下面我们来计算字符串的长度,即所有字符的个数,并简单介绍几种求字符串中指定字符个数的方法。//计算某个字符串的长度,即所有字符的个数[这计算方法是五花八门,择其优着而用之]$var=getthelengthofme$echo${var}#这里等同于$vargetthelengthofme$echo${#var}20$exprlength$var20$echo$var|awk'{printf(%d\n,length($0));}'20$echo-n$var|wc-c20//计算某些指定一个字符或者多个字符的个数$echo$var|tr-cdg|wc-c2$echo-n$var|sed-e's/[^g]//g'|wc-c2$echo-n$var|sed-e's/[^gt]//g'|wc-c5//如果要统计单词个数,更多相关信息见《shell编程之数值计算》之_单词统计_实例。$echo$var|wc-w5$echo$var|tr\n|grepget|uniq-c1$echo$var|tr\n|grepget|wc-l1说明:${}操作符在Bash里头一个“大牛”,能胜任相当多的工作,具体就看看网中人的《shell十三问》之《Shell十三问》之$(())與$()還有${}差在哪?吧。1.3字符串的存储在我们看来,字符串是一连串的字符而已,但是为了操作方便,我们往往可以让字符串呈现出一定的结构。在这里,我们不关心字符串在内存中的实际存储结构,仅仅关系它呈现出来的逻辑结构。比如,这样一个字符串:getthelengthofme,我们可以从不同的方面来呈现它。1.3.1通过字符在串中的位置来呈现它这样我们就可以通过指定位置来找到某个子串。这在c语言里头通常可以利用指针来做。而在shell编程中,有很多可用的工具,诸如expr,awk都提供了类似的方法来实现子串的查询动作。两者都几乎支持模式匹配(match)和完全匹配(index)。这在后面的字符串操作中将详细介绍。1.3.2根据某个分割符来取得字符串的各个部分这里昀常见的就是行分割符、空格或者TAB分割符了,前者用来当行号,我们似乎已经司空见惯了,因为我们的编辑器就这样“莫名”地处理着行分割符(在unix下为\n,在其他系统下有一些不同,比如windows下为\r\n)。而空格或者TAB键经常用来分割数据库的各个字段,这似乎也是司空见惯的事情。正是因为这样,所以产生了大量优秀的行编辑工具,诸如grep,awk,sed等。在“行内”(姑且这么说吧,就是处理单行,即字符串里头不再包含行分割符)的字符串分割方面,cut和awk提供了非常优越的“行内”(处理单行)处理能力。1.3.3更方便地处理用分割符分割好的各个部分同样是用到分割符,但为了更方便的操作分割以后的字符串的各个部分,我们抽象了“数组”这么一个数据结构,从而让我们更加方便地通过下标来获取某个指定的部分。bash提供了这么一种数据结构,而优秀的awk也同样提供了它,我们这里将简单介绍它们的用法。概要示例:利用数组存放getthelengthofme的用空格分开的各个部分。//1.bash提供的数组数据结构,它是以数字为下标的,和C语言从0开始的下标一样$var=getthelengthofme$var_arr=($var)#这里把字符串var存放到字符串数组var_arr中了,默认以空格作为分割符$echo${var_arr[0]}${var_arr[1]}${var_arr[2]}${var_arr[3]}${var_arr[4]}getthelengthofme$echo${var_arr[@]}#这个就是整个字符串所有部分啦,这里可以用*代替@,下同getthelengthofme$echo${#var_arr[@]}#记得上面求某个字符串的长度么,#操作符,如果想求某个数组元素的字符串长度,那么就把@换成下标吧5//你也可以直接给某个数组元素赋值$var_arr[5]=new_element$echo${var_arr[5]}6$echo${var_arr[5]}new_element//bash里头实际上还提供了一种类似于“数组”的功能,即foriin用指定分割符分开的字符串的用法//即,你可以很方便的获取某个字符串的某个部分$foriin$var;doecho-n$i;done;getthelengthofme//2.awk里头的数组,注意比较它和bash提供的数组的异同//split把一行按照空格分割,存放到数组var_arr中,并返回数组的长度。注意:这里的第一个元素下标不是0,而是1$echo$var|awk'{printf(%d%s\n,split($0,var_arr,),var_arr[1]);}'5get//实际上,上面的操作很类似awk自身的行处理功能:awk默认把一行按照空格分割为多个域,并可以通过$1,$2,$3...来获取,$0表示整行//这里的NF是该行的域的总数,类似于上面数组的长度,它同样提供了一种通过“下标”访问某个字符串的功能$echo$var|awk'{printf(%d|%s%s%s%s%s|%s\n,NF,$1,$2,$3,$4,$5,$0);}'5|getthelengthofme|getthelengthofme//awk的“数组”功能何止于此呢,看看它的for引用吧,注意,这个和bash里头的for不太一样,i不是元素本身,而是下标$echo$var|awk'{split($0,var_arr,);for(iinvar_arr)printf(%s,var_arr);}'getthelengthofme$echo$var|awk'{split($0,var_arr,);for(iinvar_arr)printf(%s,i);}'12345//awk还有更“厉害”的处理能力,它的下标可以不是数字,而可以是字符串,从而变成了“关联”数组,这种“关联”的作用在某些方便将让我们非常方便//比如,我们这里就实现一个非凡的应用,把某个文件中的某个系统调用名替换成地址,如果你真正用起它,你会感慨它的“鬼斧神工”的。//这就是我在一个场合昀好才发现的随好的实现方案:有兴趣看看awk手册帖子中我在3楼回复的实例吧。$catsymbolsys_exitsys_readsys_close$ls/boot/System.map*$awk'{if(FILENAME~System.map)map[$3]=$1;else{printf(%s\n,map[$1]
本文标题:shell编程范例之字符串操作
链接地址:https://www.777doc.com/doc-6034348 .html