python-cookbook学习笔记六

来源:互联网 发布:linux tee 用法 编辑:程序博客网 时间:2024/05/21 15:47
如果我们有一段文本内容,在输出格式上希望改变一下。比如第一行开始空格两行,或者每行显示的字符个数。可以用textwrap来达到
如下面的例子:
textwrap.fill(s,110)是设置每行的字符个数为110
textwrap.fill(s,80,initial_indent='   ')是设置每行个数为80个,其中首行以3个空格开头
textwrap.fill(s,80,subsequent_indent=' ') 是设置每行个数为80个,其中从第二行开始以一个空格开头
def text_wrap_try():    s = "Look into my eyes, look into my eyes, the eyes, the eyes, \the eyes, not around the eyes, don't look around the eyes, \look into my eyes, you're under."    print textwrap.fill(s,110)    print '\n'    print textwrap.fill(s,80,initial_indent='   ')    print '\n'    print textwrap.fill(s,80,subsequent_indent=' ')

结果如下:



字符串令牌解析:
在讲这个功能以前,首先介绍2个正则表达式的功能。第一是分组,第二个是带命名的组用法
首先看分组。下面是前面正则表达式中对于分组的定义。括号起来的表达式被一个个的分组
?
看下面的代码,字符串是<h1 class="h1user">crifan</h1>然后(\S+)(.+?)是其中2个分组匹配
def re_group():    s='<h1 class="h1user">crifan</h1>'    pattern=re.compile(r'<(\S+) class="h1user">(.+?)<\/h1>')    print pattern.search(s).group(0)    print pattern.search(s).group(1)    print pattern.search(s).group(2)
运行结果如下:可以看到group(0)输出的是整个匹配的字符串。group(1)输出的是h1也就是对应的(\S+)group(2)输出的是crifan,也就是对应的(.+?)

Group1其实对应的是网页代码的taggroup2其实对应的是网页代码的内容。通过索引值来查找对应的值不是很直观。我们能给每个分组起一个名字吗?这样通过名字来找到对应值,就好比字典的功能一样。有的,我们用如下的正则表达式。

代码改成如下:
def re_group():    s='<h1 class="h1user">crifan</h1>'    pattern=re.compile(r'<(?P<tag>\S+) class="h1user">(?P<text>.+?)<\/h1>')    print pattern.search(s).group(0)    print pattern.search(s).group('tag')    print pattern.search(s).group('text')
(\S+)和(.+?)被改成了(?P<tag>\S+)以及(?P<text>.+?)这里解释下?P<tagname>的意义,其实意义上面的说明一目了然,就是给这个分组起了个别名,那么在查找这个分组的时候可以不用索引,直接用这个别名就可以了。上面2个分组分别用了tag和text作为别名。那么在打印分组内容就可以直接使用别名,而不是索引,这样就方便多了。这里引申一下,我们再来看一个这类的高级用法。看下面的字符串,其中我们如果想匹配python study的话,后面内容中也有python study的字段。我们是否可以直接引用前面的匹配分组呢
s1='<a href="/tag/python study/">python study</a>'
代码如下:可以使用(?P=tagname) 就直接使用了之前的tag
pattern1=re.compile(r'<a href="/tag/(?P<tagname>.+?)/">(?P=tagname)<\/a>')
介绍完这2个功能后,我们在来看令牌的功能:
假设我们有一个如下字符串:
text = 'foo = 23 + 42 * 10'
我们想得到如下的结果,也就是将各个表达式分解出来,比如等号,加号以及数值

tokens= [('NAME','foo'), ('EQ','='), ('NUM','23'), ('PLUS','+'),

('NUM', '42'), ('TIMES', '*'), ('NUM', 10')]
我们尝试的代码如下
def pattern_try():
/*首先定义各个匹配模式*/    NAME = r'(?P<NAME>[a-zA-Z_][a-zA-Z_0-9]*)'    NUM = r'(?P<NUM>\d+)'    PLUS = r'(?P<PLUS>\+)'    TIMES = r'(?P<TIMES>\*)'    EQ = r'(?P<EQ>=)'    WS = r'(?P<WS>\s+)'
/*然后汇总所有的正则表达式*/    master_pat = re.compile('|'.join([NAME, NUM, PLUS, TIMES, EQ, WS]))
/*使用scanner进行字符串扫描*/    scanner = master_pat.scanner('foo = 23 + 42 * 10')    first=scanner.match()    print first.lastgroup,first.group()    first=scanner.match()    print first.lastgroup,first.group()    first=scanner.match()    print first.lastgroup,first.group()    first=scanner.match()    print first.lastgroup,first.group()
得到结果如下:可以看到每次match执行后,都能找到对应的匹配。Lastgroup输出了匹配到的字符别名,group()则是匹配到的具体字符。从上面可以看到scanner是一个可迭代的对象
E:\python2.7.11\python.exe E:/py_prj/python_cookbook.py
NAME foo
WS  
EQ =
WS  
可以优化下代码:
for m in iter(scanner.match,None):    print m.lastgroup,m.group()
得到的输出如下:
E:\python2.7.11\python.exe E:/py_prj/python_cookbook.py
NAME foo
WS  
EQ =
WS  
NUM 23
WS  
PLUS +
WS  
NUM 42
WS  
TIMES *
WS  
NUM 10

0 0
原创粉丝点击