0. 背景

之前公司的项目中,需要在嵌入式系统中实现一个http的网页端内容,由于项目历史遗留问题,公司是采用的将html文件转成c语言头文件的方式,每次修改页面端都需要从新编译一下程序,非常的繁琐。

虽然繁琐,但是因为历史遗留问题,历史遗留项目都采用这种方式做后面的升级维护。

入乡随俗嘛,用python写了一个html和h文件互转的小程序,程序编写的过程和原理很简单,以后有时间再另外发帖。(TODO)在此不做深入讨论。

程序也很好用,但是最近将公司自己写的程序使用gitblit本地仓库的形式进行版本管理后,发现一个致命的问题。就是每次转换成的h文件和公司历史遗留的文件进行git diff 时候,满屏都是不一样的地方。这咋利于版本控制和验证呢?

1. 问题分析

究竟是哪里不同呢?后来发现原来我写的转换脚本,和公司惯用的html to c脚本有着严重不同的地方在于:

公司旧版本程序是:

我转换的程序是:

git diff 比对文件的时候是会比对空格的,而且是引号的位置不同,所以就是大段的内容是不一样的。

这怎么办呢?

这时候正则匹配就派上用场了。

2. 寻找方法

上述问题其实总结起来就是:“引号位置放错了”。那么怎么知道应该在哪里放置引号呢?博主想到的笨办法就是在把每行的内容单独拎出来,然后分成三个部分,空格+内容+空格的方式,然后在组合成 空格+引号 +内容+引号+空格的方式。然后实际上就是提取出来了内容两边的东西。

talk is cheap , show codes.

假设我们有一个 test.html 文件:

 <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Hello World</h1>
</body>
</html>

我们读取它的时候,要注意,每行实际在末尾有一个换行符\n

现在我们编写一个 r.py 脚本

 import re
with open('test.html') as f:
lines = f.readlines() # 获取行列表信息
print(lines) # 打印行信息

我们在ipython中执行是这样的:

 In []: %run r.py
['<!DOCTYPE html>\n', '<html lang="en">\n', '<head>\n', '\t<meta charset="UTF-8"
>\n', '\t<title>Document</title>\n', '</head>\n', '<body>\n', '\t<h1>Hello Wor
ld</h1>\n', '</body>\n', '</html>']

2,3,4 表示的是每行的信息,和我们上面的 test.html 文件是一致的。

将上面的列表整理一下:

 # 整理列表
[
'<!DOCTYPE html>\n',
'<html lang="en">\n',
'<head>\n',
'\t<meta charset="UTF-8">\n',
'\t<title>Document</title>\n',
'</head>\n', '<body>\n',
'\t<h1>Hello World</h1>\n',
'</body>\n', '</html>'
]

可以看出,我们就是逐行打印了文件内容而已:

拿第6行举例,我们需要匹配到\t 和 \n 并在合适的地方加上引号,程序就over了。

查阅正则内容(菜鸟教程Python正则表达式章节),可知道 \s 可以匹配任意空白字符。

于是,我们用行6字符串测试一下我们的处理代码对不对:

In []: s = re.search(r'^(\s*)(.*)(\s*)$','\t"<title>Document</title>"\n')

In []: s.group()
Out[]: '\t"<title>Document</title>"\n' In []: s.group()
Out[]: '\t"<title>Document</title>"\n' In []: s.group()
Out[]: '\t' In []: s.group()
Out[]: '"<title>Document</title>"' In []: s.group()
Out[]: '\n'

测试和之前的想法是一致的。括弧括起来的内容被捕获出来。

3. 解决问题

由此,上述问题基本已经找到解决的头绪,那么定下代码编写的流程:

  1. 读取读文件
  2. 行列表信息行处理
  3. 读取写文件
  4. 写入处理后的行列表信息

于是编写代码:

 import re # 引入正则库
with open('test.html') as f: # 读取读文件
lines = f.readlines() # 读取行信息
r = r'^(\s*)(.*)(\s*)$' # 正则
lines = [re.search(r,l).group() +'"'+ re.search(r,l).group()+'\\n"'+re.search(r,l).group() for l in lines] # 处理行信息
with open('test.h','w+') as f2: # 读取写文件
f2.writelines(lines) # 写入行信息

其中第4行就是我们处理行信息的过程,这里用了一个列表推导式

所谓列表推导式,就是一种for循环的简写形式,可以从一个列表,经过一定的变换,快速生成一个列表。例如:

In[]   :  a = [,,,]
In[] : print(a)
Out[] : [,,,] In[] : print([i for i in a])
Out[] : [,,,] In[] : print([i*+ for i in a])
Out[] : [,,,]

也就是,前面第4行的程序实际上就是将lines的数据单个处理,在捕获内容中加入一些我们需要的字符,比如是双引号,然后组成了新的列表。写入到文件中。

问题解决。

4. 总结

这个测试脚本的重点就在于正则的捕获,正则捕获在文本文件、字符串处理中使用广泛,需要不断积累和总结,方能领悟其中的妙用。

python学习:python文件中空格和换行符的捕获和文本文件的转存的更多相关文章

  1. sqlserver数据库 去除字段中空格,换行符,回车符(使用replace语句)

    SQL中可以使用Replace函数来对某个字段里的某些字符进行替换操作,语法如下: 语法 REPLACE ( original-string, search-string, replace-strin ...

  2. linux下使用vim替换文件中的^M换行符

    在linux下打开windows编辑过的文本,会出现由于换行符不一致而导致的内容格式错乱的问题.最常见的就是出现^M . 我出现的问题是:在windows编辑过的文件,传到linux上后再用vim打开 ...

  3. python操作txt文件中数据教程[4]-python去掉txt文件行尾换行

    python操作txt文件中数据教程[4]-python去掉txt文件行尾换行 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文章 python操作txt文件中数据教程[1]-使用pyt ...

  4. python操作txt文件中数据教程[1]-使用python读写txt文件

    python操作txt文件中数据教程[1]-使用python读写txt文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 原始txt文件 程序实现后结果 程序实现 filename = '. ...

  5. python学习9—文件基本操作与高级操作

    python学习9—文件基本操作与高级操作 1. 文件基本操作 打开文件,获得文件句柄:f = open('filename',encoding='utf-8'),open会查询操作系统的编码方式,并 ...

  6. python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件

    python操作txt文件中数据教程[3]-python读取文件夹中所有txt文件并将数据转为csv文件 觉得有用的话,欢迎一起讨论相互学习~Follow Me 参考文献 python操作txt文件中 ...

  7. python操作txt文件中数据教程[2]-python提取txt文件

    python操作txt文件中数据教程[2]-python提取txt文件中的行列元素 觉得有用的话,欢迎一起讨论相互学习~Follow Me 原始txt文件 程序实现后结果-将txt中元素提取并保存在c ...

  8. python学习之文件读写,序列化(json,pickle,shelve)

    python基础 文件读写 凡是读写文件,所有格式类型都是字符串形式传输 只读模式(默认) r  f=open('a.txt','r')#文件不存在会报错 print(f.read())#获取到文件所 ...

  9. 使用Python从PDF文件中提取数据

    前言 数据是数据科学中任何分析的关键,大多数分析中最常用的数据集类型是存储在逗号分隔值(csv)表中的干净数据.然而,由于可移植文档格式(pdf)文件是最常用的文件格式之一,因此每个数据科学家都应该了 ...

随机推荐

  1. SQL 连贯操作 [2]

    1.alias 用于设置数据表别名 $user = M('User'); var_dump($user->alias('anothername')->select()); 这时在SQL中的 ...

  2. C++的引用的使用

    1引用的定义 引用时C++对C的一个重要的扩充,引用的作用是给变量起一个别名. 例如: int a; int &b=a;//声明b是a的引用 经过以上的声明,b就成为了a的别名,a和b的地位以 ...

  3. Freemarker 使用注意事项

    上次借助 Freemaker 模板引擎来动态构造 Kylin 访问的 SQL,在使用过程中,遇到了一些坑. ${} 输出变量时需要注意: 示例 WHERE shop_id =  ${val} 里的 v ...

  4. String/StringBuilder 类 统计字符串中字符出现的次数

    1.1. 训练描述:[方法.String类] 一.需求说明:定义如下字符串: String str = “javajfiewjavajfiowfjavagkljjava”; 二.请分别定义方法统计出: ...

  5. DB2--值为null则赋默认值

    数据库sql操作经常会做一些null值的处理.如果一个字段的值为null,我们希望查询出的结果默认设为0或空,则使用函数 COALESCE(column,0)  ,0的位置可以替换为其他值,可以是'' ...

  6. Windows cmd 将命令(/指令)写到一个文件里,直接运行这个文件。提高工作效率

    Windows cmd 批处理(cmd/bat)文件的简单使用介绍 前言 如果你想我一样,要每天都需要在cmd上,用键盘去敲击相同的命令,时间一长,你就觉得很无聊.有没有什么比较高效的方法,让我们不用 ...

  7. 激光SLAM Vs 视觉SLAM

    博客转载自:https://www.leiphone.com/news/201707/ETupJVkOYdNkuLpz.html 雷锋网(公众号:雷锋网)按:本文作者SLAMTEC(思岚科技公号sla ...

  8. JavaPersistenceWithHibernate第二版笔记-第六章-Mapping inheritance-007Inheritance of embeddable classes(@MappedSuperclass、@Embeddable、@AttributeOverrides、、)

    一.结构 二.代码 1. package org.jpwh.model.inheritance.embeddable; import javax.persistence.MappedSuperclas ...

  9. 数据结构 Job

    问题描述 有 n 项工作在等待队列中等待处理,编号为 1-n. 每个工作有个优先级 p.处理机同一时间只能处理一项工作.处理机决定接下来处理哪一项工作的方式为:从队首取出一项工作 x,若等待队列中没有 ...

  10. android 6.0(23)的权限管理

    前言 谷歌在2015年8月份时候,发布了Android 6.0版本,代号叫做“棉花糖”(Marshmallow ),其中的很大的一部分变化,是在用户权限授权上,或许是感觉之前默认授权的不合理,现在6. ...