跟散仙学shell编程(十)
上篇文章,散仙简单介绍了在linux中,使用sed和gawk编程的基础,本篇我们来复习下在正则表达式,当然不仅仅在我们的shell里面有正则,各个编程语言里面都有正则这一处理字符文本的神器。
在shell里面到处可见正则的身影:
[search@h1 820]$ ll 总用量 0 -rw-rw-r-- 1 search search 0 8月 21 02:40 ab.txt -rw-rw-r-- 1 search search 0 8月 21 02:40 acb.txt -rw-rw-r-- 1 search search 0 8月 21 02:40 bacb.txt [search@h1 820]$ ls -al 总用量 8 drwxrwxr-x 2 search search 4096 8月 21 02:40 . drwx------. 16 search search 4096 8月 21 02:22 .. -rw-rw-r-- 1 search search 0 8月 21 02:40 ab.txt -rw-rw-r-- 1 search search 0 8月 21 02:40 acb.txt -rw-rw-r-- 1 search search 0 8月 21 02:40 bacb.txt [search@h1 820]$ ls -al a* -rw-rw-r-- 1 search search 0 8月 21 02:40 ab.txt -rw-rw-r-- 1 search search 0 8月 21 02:40 acb.txt [search@h1 820]$ ls -al ab* -rw-rw-r-- 1 search search 0 8月 21 02:40 ab.txt [search@h1 820]$
在case语句里面,就充分使用了正则的表达式:
[search@h1 820]$ cat 1.sh read -p "请输入一个字符: " answer case "$answer" in one|1) echo "你选择了1" ;; two|2) echo "你选择了2" ;; three|3) echo "你选择了3" ;; *) echo "你输入了其他" ;; esac time=`date` echo "结束: $time" [search@h1 820]$ sh 1.sh 请输入一个字符: one 你选择了1 结束: 2014年 08月 21日 星期四 02:49:55 CST [search@h1 820]$ sh 1.sh 请输入一个字符: 1 你选择了1 结束: 2014年 08月 21日 星期四 02:49:58 CST [search@h1 820]$ sh 1.sh 请输入一个字符: ll 你输入了其他 结束: 2014年 08月 21日 星期四 02:50:01 CST [search@h1 820]$
[search@h1 820]$ echo "this is a test" | sed -n '/test/p' this is a test [search@h1 820]$ echo "this is a test" | sed -n '/tesst/p' [search@h1 820]$ echo "this is a test" | gawk '/test/{print $0}' this is a test [search@h1 820]$ echo "this is a test" | gawk '/tesst/{print $0}' [search@h1 820]$
正则表达式是区分大小写和单复数的:
[search@h1 820]$ echo "Aa" | sed -n '/Aa/p' Aa [search@h1 820]$ echo "Aa" | sed -n '/AA/p' [search@h1 820]$
[search@h1 820]$ echo "my name is hadoop" | sed -n '/me/p' my name is hadoop [search@h1 820]$
匹配空格:
[search@h1 820]$ echo "my name is hadoop" | sed -n '/ /p' my name is hadoop [search@h1 820]$ echo "my name is hadoop" | sed -n '/ /p'
在正则里面的转义用反斜杠\,一般会对特殊字符进行转义
[search@h1 820]$ echo "3 / 2" | sed -n '/\//p' 3 / 2 [search@h1 820]$
下面看在正则里的锚字符:
[search@h1 820]$ echo "a book " | sed -n '/^a/p' a book [search@h1 820]$ echo "is is a book " | sed -n '/^a/p' [search@h1 820]$
^代表必须以某个字符开头:
[search@h1 820]$ echo "a book" | sed -n '/$k/p' [search@h1 820]$ echo "a book" | sed -n '/k$/p' a book [search@h1 820]$ echo "a book c" | sed -n '/k$/p' [search@h1 820]$
$代表以某个字符结尾
[search@h1 820]$ echo "a fish" | sed -n '/^a fish$/p' a fish [search@h1 820]$ echo "a b fish" | sed -n '/^a fish$/p' [search@h1 820]$
如果以^开头以$结尾的表达式,代表必须匹配这样的模式,不能出现在字符串里的任意位置
[search@h1 820]$ cat v.txt this is a test of line this cat is sleeping this ia a very nice hat this test is at line four [search@h1 820]$ sed -n '/.at/p' v.txt this cat is sleeping this ia a very nice hat this test is at line four [search@h1 820]$
.字符代表一个字符,必须匹配一个字符
下面看下字符组[],表示可以匹配方括号内的任意一个字符
[search@h1 820]$ echo "Yes" | sed -n '/[Yy]es/p' Yes [search@h1 820]$ echo "yes" | sed -n '/[Yy]es/p' yes [search@h1 820]$
排除字符组[^]:
[search@h1 820]$ cat b.txt cat hat hadoop oops gat mat yat [search@h1 820]$ sed -n '/[^hm]at/p' b.txt cat gat yat [search@h1 820]$
当然我们也可以使用区间:
[search@h1 820]$ echo "90" | sed -n '/[0-8]0/p' [search@h1 820]$ echo "90" | sed -n '/[0-9]0/p' 90 [search@h1 820]$
在shell里面还有一些特殊的字符组:
[[:alpha:]]匹配任意字母字符,无论是大写还是小写
[[:alnum:]]匹配任意字母数字字符0-9,a-Z,或a-z
[[:blank:]]匹配空格或制表符
[[:digit:]]匹配0-9之间的数字
[[:lower:]]匹配小写字母字符a-z
[[:print:]]匹配任意可打印字符
[[:punct:]]匹配标点符号
[[:space:]]匹配任意空白字符,空格,制表符,NL,FF,VT,CR
[[:upper:]]匹配任意大写字母字符A-Z
[search@h1 820]$ echo "abc" sed -n '/[[:digit:]]/p' abc sed -n /[[:digit:]]/p [search@h1 820]$ echo "abc" | sed -n '/[[:digit:]]/p' [search@h1 820]$ echo "abc123" | sed -n '/[[:digit:]]/p' abc123 [search@h1 820]$
下面看下*号,表示0个到多个字符:
[search@h1 820]$ echo "ik" | sed -n '/ie*k/p' ik [search@h1 820]$ echo "ik" | sed -n '/iee*k/p' [search@h1 820]$ echo "iek" | sed -n '/iee*k/p' iek [search@h1 820]$
[search@h1 820]$ echo "bat" | sed -n '/b[ba]*t/p' bat [search@h1 820]$ echo "bt" | sed -n '/b[ba]*t/p' bt [search@h1 820]$ echo "bta" | sed -n '/b[ba]*t/p' bta [search@h1 820]$ echo "bta" | sed -n '/^b[ba]*t$/p' [search@h1 820]$
下面看下?号字符,代表0个或1个:
[search@h1 820]$ echo "bt" | gawk '/bt?/{print $0}' bt [search@h1 820]$ echo "btt" | gawk '/bt?/{print $0}' btt [search@h1 820]$ echo "btta" | gawk '/bt?/{print $0}'
下面看下+号,表示字符必须出现一次:
[search@h1 820]$ echo "bt" | gawk '/bt+/{print $0}' bt [search@h1 820]$ echo "bbt" | gawk '/bt+/{print $0}' bbt [search@h1 820]$ echo "bbz" | gawk '/bt+/{print $0}' [search@h1 820]$
下面看下如何使用大括号来控制范围:
{m}出现m次
{m,n}在一个m到n的范围内
{m,}至少出现m次
[search@h1 820]$ echo "bt" | gawk --re-interval '/be{1,2}/{ print $0}' [search@h1 820]$ echo "bet" | gawk --re-interval '/be{1,2}/{ print $0}' bet [search@h1 820]$ echo "beet" | gawk --re-interval '/be{1,2}/{ print $0}' beet [search@h1 820]$ echo "beeet" | gawk --re-interval '/be{1,2}/{ print $0}' beeet [search@h1 820]$
[search@h1 820]$ echo "bt" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "bat" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' bat [search@h1 820]$ echo "bet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' bet [search@h1 820]$ echo "baet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' baet [search@h1 820]$ echo "baaet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "baet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' baet [search@h1 820]$ echo "baeat" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "bat" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' bat [search@h1 820]$ echo "bant" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "baaeet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "baet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' baet [search@h1 820]$ echo "baeaet" | gawk --re-interval '/b[ae]{1,2}t/{ print $0 }' [search@h1 820]$ echo "baeaet" | gawk --re-interval '/b[ae]{1,4}t/{ print $0 }' baeaet [search@h1 820]$ echo "baeaet" | gawk --re-interval '/b[ae]{1,3}t/{ print $0 }' [search@h1 820]$
注意这个范围的m,n,比如[ae]{1,2},后面的n代表匹配的最大次数,最多能同时出现ae,
也可以使用|符号:
[search@h1 820]$ echo "this is a dog" | gawk '/cat|dog/ { print $0 }' this is a dog [search@h1 820]$ echo "this is a ddog" | gawk '/cat|dog/ { print $0 }' this is a ddog [search@h1 820]$ echo "this is a ddoxg" | gawk '/cat|dog/ { print $0 }' [search@h1 820]$ echo "this is a cat" | gawk '/cat|dog/ { print $0 }' this is a cat [search@h1 820]$
如果想匹配整个字符串,需要使用()标识整体:
[search@h1 820]$ echo "satabcd" | gawk '/sat(abc)?/ {print $1}' satabcd [search@h1 820]$
下面看个小实站例子,目录文件计数:
[root@h1 ~]# cat count.sh mypath=`echo $PATH | sed 's/:/ /g'` echo $mypath count=0 for dir in $mypath do check=`ls $dir` for item in $check do count=$[ $count + 1 ] done echo "$dir的数量: $count" count=0 done [root@h1 ~]# sh count.sh . /usr/local/sbin /usr/local/bin /sbin /bin /usr/sbin /usr/bin /usr/local/jdk/bin /home/search/hadoop/bin /home/search/hadoop/sbin /usr/local/ant/bin /usr/local/maven/bin /home/search/hive/bin /home/search/hive/conf /root/bin .的数量: 32 /usr/local/sbin的数量: 0 /usr/local/bin的数量: 0 /sbin的数量: 238 /bin的数量: 93 /usr/sbin的数量: 157 /usr/bin的数量: 588 /usr/local/jdk/bin的数量: 45 /home/search/hadoop/bin的数量: 11 /home/search/hadoop/sbin的数量: 27 /usr/local/ant/bin的数量: 13 /usr/local/maven/bin的数量: 6 /home/search/hive/bin的数量: 10 /home/search/hive/conf的数量: 4 ls: 无法访问/root/bin: 没有那个文件或目录 /root/bin的数量: 0 [root@h1 ~]#
至此,我们统计文件的小脚本就完成了,有兴趣的朋友,可以在linux里面尝试一下电话号码和邮箱的验证的正则的使用!