SHELL的字符替换
SHELL的字符替换


shell的字符替换

变量替换:
一:简单赋值和替换
a=bcd
$ echo $a 
bcd
$ echo ${a}    ????
bcd
二:变量扩充
除了shell中的meta,其它的[^a-zA-Z0-9_]几乎都可以作单词边界。
sed中关于单词边界[^a-zA-Z0-9_]的描述。
bbs.chinaunix/forum/24/20040825/393964.html
这些功能有时候会在程序中有意想不到的作用!
例如:
$ a=bcd
$ echo ${a}.b
bcd.b
$ echo $a.php
bcd.php
$ echo $a%b
bcd%b
$ echo /$a/bc
/bcd/bc
对于shell中的meta字符,则backslash
$ echo $a\*b
bcd*b
三:变量中的变量
$ a=bcd
$ b=efg
$ c=$a$b
$ echo $c
bcdefg
$ d=$c.ghi
$ echo $d
bcdefg.ghi
思考:若变量互相嵌套,会怎样呢?
四:变量的特异功能
到网中人的啦!(ps:重写真是没激情啊)
file=/dir1/dir2/dir3/
我们可以用 ${ } 分别替换获得不同的值:
${file#*/}:从变量file的字符串左边开始,删除字符直到第一个“/”dir1/dir2/dir3/
${file##*/}:从变量file字符串长度1是什么意思的字符串左边开始,删除字符直到最后一个“/”
${file#*.}:从变量file的字符串左边开始,删除字符直到第一个“.”
${file##*.}:从变量file的字符串左边开始,删除字符直到最后一个“.”txt
其实,在“#”后面,无非就是一个匹配问题,不限于两个,你可以放任意个字符,还可以用shell中另外的通配符“?”“[…]”“[!…]”,例如:
$ echo ${file#????}
1/dir2/dir3/
$ echo ${file#*[0-9]}
/dir2/dir3/
$ echo ${file#/dir1/dir[0-9]}
/dir3/
“#”:相当于最小匹配,遇到一个最小的符合其后表达式的字符串(单个或多个)即中止匹配动作;
“##”:相当于最大匹配,它尽可能的匹配更多的字符。
我们可以拿“*”来说明: 
shell中表示匹配任何符号包括空。当它在只有一个 # 的变量替换中,受最小匹配的影响,它不会匹配任何可打印字符,只匹配一个空,也就是什么也不匹配,你完全可以忽略它的存在;
当在有两个 ## 的变量替换中,受最大匹配的影响,一个 * 表示匹配整个字符串。
如果想匹配字符“*”时,要在“*”前加一个“\”,其后的“*”失去通配符的功能。
但是还有一种例外情况(请接着看)
例:
$ file2=abcd.pp
$ echo ${file2#*.*.*.*}
$ echo ${file2##*.*.*.*}
想想上面两个的输出是什么?
$ echo ${file2#*.*.*.*}
oopp
$ echo ${file2##*.*.*.*}

??知道为什么吗?因为:“*”匹配任何符号包括空。遇到一个“#”时,最后一个“*”就匹配去了。看下面的:
$ echo ${file2#*.*.*.?}
opp
$ echo ${file2#*.*.*.?*}
opp
$ echo ${file2##*.*.*.?}
opp
$ echo ${file2##*.*.*.?*}

do you know
$ echo $file3
*ab*de*cd
看看下面将输出什么?
$ echo ${file3#*ab}     
*de*cd
$ echo ${file3#**}
*ab*de*cd
$ echo ${file3##**}

$ echo ${file3#\*ab}
*de*cd
$ echo ${file3#\**}
ab*de*cd
$ echo ${file3##\**}

$ echo ${file3#*a}
b*de*cd
$ echo ${file3#\*a}
b*de*cd
不知各位有没有发现,“*”在一个“#”中时,并不一定代表,它可能代表一个字符“*”也可能代表其他的什么字符,如上例的:
“$ echo ${file3#*a}”输出为“b*de*cd”,其实这还是符合最小匹配理论的。这个表达式的意思是:从变量file3的字符串左边开始删除字符,直到遇到第一个字符“a”。所以不要和“$ echo ${file3#\*a}”混淆,虽然两个结果是一样,但意思是不一样的。
再举几个例子,相信大家更容易理解这段话:
$ echo $file3
*ab*de*cd*ab*de                    //注意:出现两个“*ab”
$ echo ${file3#*a}
b*de*cd*ab*de                        //删除字符,直到出现第一个“a”“*”为通配符
$ echo ${file3##*a}
b*de                                          //删除字符,直到出现第二个“a”“*”为通配符
$ echo ${file3##\*a}
b*de*cd*ab*de                        //删除字符串“*a”“*”“\”表示字符“*”
除了通配符“*”比较难理解一点,其他的shell通配符就都很容易了。
至于“%”,和“#”不同的地方,就是从变量字串右部开始。
${file%/*}:从右部开始拿掉字符,直到遇到(从右部数起的)第一个“/” /dir1/dir2/dir3
${file%%/*}:从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“/”(空值)
${file%.*}:从右部开始拿掉字符,直到遇到(从右部数起的)第一个“.”/dir1/dir2/dir3/my.file
${file%%.*}:从右部开始拿掉字符,直到遇到(从右部数起的)最后一个“.”/dir1/dir2/dir3/my
单匹配格式${var/被替换字符/替换字符}
全匹配格式${var//被替换字符/替换字符}
例子:
[test]# echo ${ip/./@}
324@2354.329.5324
[test]# echo ${ip/./,}
324,2354.329.5324
[test]# echo ${ip/./ }
324 2354.329.5324
[test]# echo ${ip//./ }
324 2354 329 5324
[test]# echo ${ip//./,}
324,2354,329,5324
[test]# echo ${ip//./@}
[email=324@2354@329@5324]324@2354@329@5324[/email]
总结一点结果.${}:
/代表字符串的替换.
:代表字符串的提取.
#%公别代表左截和右截.
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" | grep "<tab>" #<tab>为在键盘上按下TAB键,而不是字符<tab>
// 匹配邮件地址
$ echo "test2007@lzu" | grep "[0-9a-zA-Z\.]*@[0-9a-zA-Z\.]"
test2007@lzu
// 匹配URL地址(http链接为例)
$ echo "news.lzu.edu/article.jsp?newsid=10135" | grep "[0-9a-zA-Z\./=?]*"
news.lzu.edu/article.jsp?newsid=10135
说明:
[1] /dev/null/dev/zero是非常有趣的两个设备,它们都犹如一个黑洞,什么东西掉进去都会消失殆尽;后者则是一
个能源箱,你总能从那里取到0,直到你退出。两者的部分用法见:关于zeroNULL设备的一些问题
[2] [[:space:]]grep用于匹配空格或者TAB键类型字符串的一种标记,其他类似的标记请查看grep的帮助,man
grep
[3] 上面都是用grep来进行模式匹配,实际上sed, awk都可以用来做模式匹配,关于匹配中用到的正则匹配模式知识,
大家可以参考正则匹配模式,更多相关资料请看参考资料。
[4] 如果仅仅想判断字符串是否为空,即判断字符串的长度是否为零,那么可以简单的通过test命令的-z选项来判断,
具体用法见test命令,man test.
概要示例: 判断字符是否可打印?如何控制字符在终端的显示。
// 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;29H Hello, World\!" #在屏幕的第11行,29列开始打印字符串Hello,World!
// 在屏幕的某个位置动态显示当前系统时间
$ while :; do echo -e "\33[11;29H "$(date "+%Y-%m-%d %H:%M:%S"); done
// col命令过滤掉某些控制字符,在处理诸如script,screen等截屏命令的输出结果时,很有用
$ screen -L
$ cat /bin/cat
$ exit
$ cat screenlog.0 | col -b  # 把一些控制字符过滤后,就可以保留可读的操作日志
更多关于字符在终端的显示控制方法,请参考资料[20]和字符显示实例[21]:用shell实现的一个动态时钟。
1.2 字符串的长度
概要示例: 除了组成字符串的字符类型外,字符串还有哪些属性呢?组成字符串的字符个数。下面我们来计算字符串的
长度,即所有字符的个数,并简单介绍几种求字符串中指定字符个数的方法。
// 计算某个字符串的长度,即所有字符的个数[这计算方法是五花八门,择其优着而用之]
$ var="get the length of me"
$ echo ${var}    # 这里等同于$varget the length of me
$ echo ${#var}
20
$ expr length "$var"
20
$ echo $var | awk '{printf("%d\n", length($0));}'
20
$ echo -n $var |  wc -c
20
// 计算某些指定一个字符或者多个字符的个数
$ echo $var | tr -cd g | wc -c
2
$ echo -n $var | sed -e 's/[^g]//g' | wc -c
2
$ echo -n $var | sed -e 's/[^gt]//g' | wc -c
5
// 如果要统计单词个数,更多相关信息见《shell编程之数值计算》之 _单词统计_ 实例。
$ echo $var | wc -w
5
$ echo "$var" | tr " " "\n" | grep get | uniq -c
1
$ echo "$var" | tr " " "\n" | grep get | wc -l
1
说明:
${}操作符在Bash里头一个大牛,能胜任相当多的工作,具体就看看网中人的《shell十三问》之《Shell十三问》
"$(( )) $( ) 還有${ } 差在哪?" 吧。
1.3 字符串的存储
在我们看来,字符串是一连串的字符而已,但是为了操作方便,我们往往可以让字符串呈现出一定的结构。在这里,我
们不关心字符串在内存中的实际存储结构,仅仅关系它呈现出来的逻辑结构。比如,这样一个字符串:"get the
length of me",我们可以从不同的方面来呈现它。
1.3.1 通过字符在串中的位置来呈现它
这样我们就可以通过指定位置来到某个子串。这在c语言里头通常可以利用指针来做。而在shell编程中,有很多可用

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