跟散仙学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里面尝试一下电话号码和邮箱的验证的正则的使用!