文本处理:
假设你存在一个目录,下面存在各种形式的文件,有txt,csv等等。如果你只想找到其中一种或多种格式的文件并打开该如何办呢。首先肯定是要找到满足条件的文件,然后进行路径合并在一一打开。
path=r'D:\test_source'
filenames=os.listdir(path)
print filenames
ret=[name for name in filenames if name.endswith('.txt')]
print ret
direct_path=[os.path.join(path,r) for r in ret]
print direct_path[0]
运行结果如下:
['1.csv', 'info.txt', 'pycharm2.jpg']
['info.txt']
D:\test_source\info.txt
这个代码中listdir是列出该目录下的所有文件名称。可以看到其中有txt,csv,jpg的文件
[name for name in filenames if name.endswith('.txt')] 这个是找出其中所有txt文件。其中使用到了name.endswith,endswith的功能就是找到所有满足后缀条件的文件。
找到满足的条件后最后用[os.path.join(path,r) for r in ret] 进行路径归并。最后得到完整的满足条件的文件路径。
那么既然有判断结尾的,有没有可以判断开头的呢。Startswith这个就是判断开头的。
[name for name in filenames if name.startswith('1')]
这样就把以1开头的文件找出来了。
那么继续发散一下,假如我有如下的文件:假如我只是想以数字开头的txt文件找出来。该如何找呢

这种情况下需要用到正则表达式来进行匹配,但是endswith和startswith中并不能匹配正则表达式。下面介绍一种功能更强大的功能fnmatch.
方法如下:
可以看到fnmatch中我们用到了正则表达式的方法将以数字开头的txt文件给找出来
ret=[name for name in filenames if fnmatch(name,'[0-9].txt')]
再看下面的方法:这个是匹配所有py开头的文件
ret=[name for name in filenames if fnmatch(name,'py*')]
得到的结果如下:
['py_log.txt', 'py_result.jpg']
 
 
 
如果我们有一段文本内容,在输出格式上希望改变一下。比如第一行开始空格两行,或者每行显示的字符个数。可以用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其实对应的是网页代码的tag,group2其实对应的是网页代码的内容。通过索引值来查找对应的值不是很直观。我们能给每个分组起一个名字吗?这样通过名字来找到对应值,就好比字典的功能一样。有的,我们用如下的正则表达式。

代码改成如下:
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



												

python cookbook第三版学习笔记四:文本以及字符串令牌解析的更多相关文章

  1. python cookbook第三版学习笔记十:类和对象(一)

    类和对象: 我们经常会对打印一个对象来得到对象的某些信息. class pair:     def __init__(self,x,y):         self.x=x         self. ...

  2. python cookbook第三版学习笔记十三:类和对象(四)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  3. python cookbook第三版学习笔记十四:类和对象(五)代理类以及内存回收

    代理类: 代理类的作用其实有继承有些类似,如果你想将某个实例的属性访问代理到内部另外一个实例中去,可以用继承也可以用代理.来看下代理的应用: class A:     def spam(self,x) ...

  4. python cookbook第三版学习笔记六:迭代器与生成器

    假如我们有一个列表 items=[1,2,3].我们要遍历这个列表我们会用下面的方式 For i in items:   Print i 首先介绍几个概念:容器,可迭代对象,迭代器 容器是一种存储数据 ...

  5. python cookbook第三版学习笔记十一:类和对象(二)调用父类的方法

    在子类中调用父类的方法,可以下面的A.spam(self)的方法. class A(object):     def spam(self):         print 'A.spam' class ...

  6. python cookbook第三版学习笔记 一

    数据结构 假设有M个元素的列表,需要从中分解出N个对象,N<M,这会导致分解的值过多的异常.如下: record=['zhf','zhf@163.com','775-555-1212','847 ...

  7. python cookbook第三版学习笔记十三:类和对象(三)描述器

    __get__以及__set__:假设T是一个类,t是他的实例,d是它的一个描述器属性.读取属性的时候T.d返回的是d.__get__(None,T),t.d返回的是d.__get__(t,T).说法 ...

  8. python cookbook第三版学习笔记二十:可自定义属性的装饰器

    在开始本节之前,首先介绍下偏函数partial.首先借助help来看下partial的定义 首先来说下第一行解释的意思: partial 一共有三个部分: (1)第一部分也就是第一个参数,是一个函数, ...

  9. python cookbook第三版学习笔记十六:抽象基类

    假设一个工程中有多个类,每个类都通过__init__来初始化参数.但是可能有很多高度重复且样式相同的__init__.为了减少代码.我们可以将初始化数据结构的步骤归纳到一个单独的__init__函数中 ...

随机推荐

  1. Docker镜像原理和最佳实践

    https://yq.aliyun.com/articles/68477 https://yq.aliyun.com/articles/57126  DockerCon 2016 深度解读: Dock ...

  2. Android Spinner In Toolbar

    As the title of the post suggest in this tutorial we will see how to have spinner widget inside the ...

  3. 【spring cloud】【spring boot】项目启动报错:Cannot determine embedded database driver class for database type NONE

    解决参考文章:https://blog.csdn.net/hengyunabc/article/details/78762097 spring boot启动报错如下: Error starting A ...

  4. Java程序员新手老手都离不开八大开发工具

    以下这8个工具,从代码构建到错误挤压,覆盖Java开发的全域.学习这些工具可以帮助你改善代码质量,成为一个更高效的Java开发人员.Java这个大世界中正在不断涌现新的工具.实用程序和库.如果你的首选 ...

  5. android图片素材參考

    hpi:通常是大图像素是:480x800   (640*960)宽比长大致为0.6左右      一般240dpi.    小图的像素依据实际来. xhdi:一般大图像素是: 640x1136 (72 ...

  6. 解决Linux中文环境下astro和Calibre不能输入的问题

    例如我的opensuse在中文环境下不能在astro中输入指令,Calibre的grid spacing设置框不能输入,经过摸索,找到以下两种解决方法: 1.    将系统环境变成英文,在.bashr ...

  7. 如何使用CocoaPods安装使用及配置私有库以及管理依赖库 【原创】

    CocoaPods是什么 在iOS开发中势必会用到一些第三方依赖库,比如大家都熟悉的ASIHttpRequest.AFNetworking.JSONKit等.使用这些第三方类库能极大的方便项目的开发, ...

  8. ubantu 下 修改mysql 默认编码

    启动mysql后,以root登录mysql root@Eadgar-virtual-machine:~# mysql -uroot -proot mysql> show variables li ...

  9. ASP.NET页面间传值的几种方式

    ASP.NET页面间传值的几种方式 1.使用QueryString 使用QuerySting在页面间传递值已经是一种很老的机制了,这种方法的主要优点是实现起来非常简单,然而它的缺点是传递的值是会显示在 ...

  10. oauth学习

    https://www.cnblogs.com/blowing00/p/4524132.html