《linux命令行与shell脚本编程大全》第三版

来源:互联网 发布:乌鲁木齐网络蛋糕店 编辑:程序博客网 时间:2024/06/15 16:08
《linux命令行与shell脚本编程大全》
全书4部分:
☆ 【1】linux命令行(1-10章)
☆ 【2】shell脚本编程基础(11-16章)
☆ 【3】高级shell脚本编程(17-23章):正则表达式
☆ 【4】创建实用的脚本(24-26章)


>>第20章丶正则表达式


正则表达式
:定义的模式模板(pattern template),Linux工具可以用它来过滤文本。
如果匹配了定义的模式,它就会被接受并进一步处理;如果数据不匹配模式,它就会被滤掉。
在Linux中,有两种流行的正则表达式引擎:
 POSIX基础正则表达式(basic regular expression, BRE)引擎
 POSIX扩展正则表达式(extended regular expression, ERE)引擎


BRE模式--纯文本
正则表达式第一条原则就是:'正则表达式模式都区分大小写
$ echo "The books are expensive" | sed -n '/book/p'
The books are expensive

BRE模式--特殊字符
正则表达式识别的特殊字符包括:.*[]^${}\+?|()
特殊字符作为文本字符,就必须转义,转义字符:是反斜线(\)。
$ echo "3 / 2" | sed -n '/\//p'
3 / 2

BRE模式--锚字符
1. 锁定在行首
脱字符(^)定义从数据流中文本行的行首开始的模式。
$ echo "This ^ is a test" | sed -n '/s ^/p'
This ^ is a test
// 如果指定正则表达式模式时只用了脱字符,就不需要用反斜线来转义。但如果你在模式中先指定了脱字符,随后还有其他一些文本,那么你必须在脱字符前用转义字符。

2. 锁定在行尾

特殊字符美元符($)定义了行尾锚点。
$ echo "This is a good book" | sed -n '/book$/p'
This is a good book
// 要想匹配,文本模式必须是行的最后一部分。比如 sed -n '/boo$/p' 就不能实现匹配

3. 组合锚点

行首和行尾同时使用。
$ cat data5
This is one test line.
This is another test line.
$ sed '/^$/d' data5
This is one test line.
This is another test line.

BRE模式--点号字符
特殊字符点号用来匹配除换行符之外的任意单个字符。它必须匹配一个字符,如果在点号字符的位置没有字符,那么模式就不成立。
$ cat data6
This is a test of a line.
The cat is sleeping.
That is a very nice hat.
This test is at line four.
at ten o'clock we'll go home.
$ sed -n '/.at/p' data6
The cat is sleeping.
That is a very nice hat.
This test is at line four.
// 'cat' 'hat' ' at' 都可以匹配;而'a t'不能匹配。

BRE模式--字符组
字符组中必须有个字符来匹配相应的位置。
$ cat data7
This line doesn't contain a number.
This line has 1 number on it.
This line a number 2 on it.
This line has a number 4 on it.
$ sed -n '/[0123]/p' data7
This line has 1 number on it.
This line a number 2 on it.
如果要确保只匹配五位数,就必须将匹配的字符和其他字符分开,要么用空格,要么指明它们就在行首和行尾。
$ sed -n '
> /^[0123456789][0123456789][0123456789][0123456789][0123456789]$/p
> ' data8

60633
46201
22203
// 过滤出data8中只有5个字符的邮编。
字符组的一个极其常见的用法是"解析拼错的单词",比如用户表单输入的数据。
$ cat data9
I need to have some maintenence done on my car.
I'll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.
$ sed -n '
> /maint[ea]n[ae]nce/p
> /sep[ea]r[ea]te/p
> ' data9

I need to have some maintenence done on my car.
I'll pay that in a seperate invoice.
After I pay for the maintenance my car will be as good as new.

BRE模式--排除型字符组
可以寻找组中没有的字符,而不是去寻找组中含有的字符。
$ sed -n '/[^ch]at/p' data6
This test is at line four.

BRE模式--特殊的字符组
组          描 述
[[: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
$ echo "abc" | sed -n '/[[:digit:]]/p'
$
$ echo "abc" | sed -n '/[[:alpha:]]/p'
abc
$ echo "abc123" | sed -n '/[[:digit:]]/p'
abc123
$ echo "This is, a test" | sed -n '/[[:punct:]]/p'
This is, a test

BRE模式--区间

可以用单破折线符号在字符组中表示字符区间。
$ sed -n '/^[0-9][0-9][0-9][0-9][0-9]$/p' data8
60633
46201
45902
也适用于字母。
$ sed -n '/[c-h]at/p' data6
The cat is sleeping.
That is a very nice hat.
可以在单个字符组指定多个不连续的区间。
$ sed -n '/[a-ch-m]at/p' data6
The cat is sleeping.
That is a very nice hat.

BRE模式--星号
在字符后面放置星号表明该字符必须在匹配模式的文本中出现0次或多次
$ echo "I ate a potatoe with my lunch." | sed -n '/potatoe*/p'
I ate a potatoe with my lunch.
将点号特殊字符和星号特殊字符组合起来。这个组合能够匹配任意数量的任意字符。它通常用在数据流中两个可能相邻或不相邻的文本字符串之间。
$ echo "this is a regular pattern expression" | sed -n '
> /regular.*expression/p'

this is a regular pattern expression

扩展--问号
问号表明前面的字符可以出现0次或1次,但只限于此。它不会匹配多次出现的字符。
$ echo "bt" | gawk '/be?t/{print $0}'
bt
$ echo "bet" | gawk '/be?t/{print $0}'
bet

扩展--加号
加号表明前面的字符可以出现1次或多次,但必须至少出现1次。如果该字符没有出现,那么模式就不会匹配。
$ echo "beeet" | gawk '/be+t/{print $0}'
beeet
$ echo "beet" | gawk '/be+t/{print $0}'
beet
$ echo "bet" | gawk '/be+t/{print $0}'
bet
$ echo "bt" | gawk '/be+t/{print $0}'
$

扩展--花括号
间隔(interval),可以用两种格式来指定区间。
 m:正则表达式准确出现m次。
 m, n:正则表达式至少出现m次,至多n次。

这个特性可以精确调整字符或字符集在模式中具体出现的次数。
// 默认情况下, gawk程序不会识别正则表达式间隔。必须指定gawk程序的--re- interval命令行选项才能识别正则表达式间隔。
$ echo "bt" | gawk --re-interval '/be{1}t/{print $0}'
$
$ echo "bet" | gawk --re-interval '/be{1}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1}t/{print $0}'
$
字符e可以出现1次或2次,这样模式就能匹配;否则,模式无法匹配:
$ echo "bet" | gawk --re-interval '/be{1,2}t/{print $0}'
bet
$ echo "beet" | gawk --re-interval '/be{1,2}t/{print $0}'
beet

扩展--管道符号
管道符号允许你在检查数据流时,用逻辑OR方式指定正则表达式引擎要用的两个或多个模式。
使用管道符号的格式如下:
    expr1|expr2|...
$ echo "The cat is asleep" | gawk '/cat|dog/{print $0}'
The cat is asleep
$ echo "The dog is asleep" | gawk '/cat|dog/{print $0}'
The dog is asleep
$ echo "The sheep is asleep" | gawk '/cat|dog/{print $0}'
$
这个例子会匹配数据流文本中的cat、 hat或dog。
$ echo "He has a hat." | gawk '/[ch]at|dog/{print $0}'
He has a hat.

扩展--表达式分组
可以用圆括号()进行分组。
$ echo "Sat" | gawk '/Sat(urday)?/{print $0}'
Sat
$ echo "Saturday" | gawk '/Sat(urday)?/{print $0}'
Saturday
结尾的urday分组以及问号,使得模式能够匹配完整的Saturday或缩写Sat。
分组和管道符号一起使用来创建可能的模式匹配组是很常见的做法:
$ echo "cat" | gawk '/(c|b)a(b|t)/{print $0}'
cat
$ echo "cab" | gawk '/(c|b)a(b|t)/{print $0}'
cab
$ echo "bat" | gawk '/(c|b)a(b|t)/{print $0}'
bat
$ echo "bab" | gawk '/(c|b)a(b|t)/{print $0}'
bab
$ echo "tab" | gawk '/(c|b)a(b|t)/{print $0}'
$
$ echo "tac" | gawk '/(c|b)a(b|t)/{print $0}'
$

正则表达式实战--目录文件计数
对PATH环境变量中定义的目录里的可执行文件进行计数:
/* PATH环境变量包含的目录中文件计数 */#!/bin/bash# count number of files in your PATHmypath=$(echo $PATH | sed 's/:/ /g')count=0for directory in $mypathdo    check=$(ls $directory)    for item in $check    do        count=$[ $count + 1 ]    done    echo "$directory - $count"    count=0done
$ ./countfiles
/usr/local/sbin - 0
/usr/local/bin - 2
/usr/sbin - 213
/usr/bin - 1427
/sbin - 186
/bin - 152
/usr/games - 5
/usr/local/games – 0

正则表达式实战--验证电话号码
在美国,电话号码有几种常见的形式:
(123)456-7890
(123) 456-7890
123-456-7890
123.456.7890
/* 脚本代码演示 */#!/bin/bash# script to filter out bad phone numbersgawk --re-interval '/^\(?[2-9][0-9]{2}\)?(| |-|\¬[0-9]{3}( |-|\.)[0-9]{4}/{print $0}'
$ cat phonelist
000-000-0000
123-456-7890
212-555-1234
(317)555-1234
(202) 555-9876
33523
1234567890
234.123.4567
$ cat phonelist | ./isphone
212-555-1234
(317)555-1234
(202) 555-9876
234.123.4567

正则表达式实战--解析邮件地址
邮件地址的基本格式为:username@hostname
username值可用字母数字字符以及以下特殊字符:
 点号
 单破折线
 加号
 下划线

服务器名和域名也必须遵照严格的命名规则,只允许字母数字字符以及以下特殊字符:
 点号
 下划线

/* 脚本代码演示 */#!/bin/bash# script to filter out bad phone numbersgawk --re-interval '/^([a-zA-Z0-9_\-\.\+]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$/{print $0}'
$ echo "rich@here.now" | ./isemail
rich@here.now
$ echo "rich@here.now." | ./isemail
$
$ echo "rich_blum@here.now" | ./isemail
rich_blum@here.now
$ echo "rich/blum@here.now" | ./isemail
$

sed和gawk进阶版(目前未涉及,暂略)



2017.07.09
第20章完...(全书未完待续!)
原创粉丝点击