一、概述
大家都知道linux的一些命令例如sed、awk可以实现对文件内容的修改,那么python能否实现类似的功能,最近刚好工作上有处理文件内容的需求,所以研究了一下python在处理文件内容方面的功能。
二、在指定的关键字前/后插入内容
在指定的关键字前/后插入内容是一个比较常见的需求,我们先来看下在关键字之前插入内容怎么实现。
有时候我们做一些复杂的功能,碰到有些逻辑想不明白的时候,可以把环境简化一些,用最简单的demo来帮助自己理解,还是比较有效的。
先看简单的例子。
基于 [在数字6前面插入数字5] 这样的需求,写了以下一段代码。
def add_content_before_keyword():
tmp = '1234678'
index = tmp.find('6')
print('数字6在字符串tmp中的位置是:{}'.format(str(index)))
add_num = '5'
part_ahead = tmp[:index]
# 因为Python的切片包含起始索引本身的值,例如list[5:10]的切片中是包含list[5]本身的值的,所以这里直接使用[index:]即可
part_behind = tmp[index:]
print('字符串前半部分切片的值是:{}'.format(str(part_ahead)))
print('字符串后半部分切片的值是:{}'.format(str(part_behind)))
tmp_modified = part_ahead + add_num + part_behind
print('插入数字5之后,新的字符串为:{}'.format(tmp_modified))
add_content_before_keyword()
运行结果:
数字6在字符串tmp中的位置是:4
字符串前半部分切片的值是:1234
字符串后半部分切片的值是:678
插入数字5之后,新的字符串为:12345678
Process finished with exit code 0
在这个例子中,总体上看一共做了三件事:
1.获取关键字的下标(我们要在某个关键字前/后插入内容,那肯定需要根据自己的需求场景确定一个关键字,这里关键字是6)
2.将待处理的文本内容(1234678)通过第一步获取的关键字下标,进行切片,分割成两个部分
3.将数字5和第二步切片得到的文本重新组成一个新的字符串(12345678)
那么再来看一下在关键字后面加入指定的内容,例如下面这个例子:
需求:在数字5之后插入数字6
def add_content_after_keyword():
tmp = '1234578'
index = tmp.find('5')
print('数字5在字符串tmp中的位置是:{}'.format(str(index)))
add_num = '6'
# Python的切片是不包含 终止索引 本身的值,例如list[0:7]不包含list[7]本身的值,所以这里要加上len(add_num),增加终止索引的下标
part_ahead = tmp[:index+len(add_num)]
# Python的切片包含 起始索引 本身的值,例如list[0:10]是包含list[0]本身的值的,而我们这里的目标是获取字符串关键字之后的部分,索引需要加上len(add_num)以避免切片的内容包含关键字本身
part_behind = tmp[index+len(add_num):]
print('字符串前半部分切片的值是:{}'.format(str(part_ahead)))
print('字符串后半部分切片的值是:{}'.format(str(part_behind)))
tmp_modified = part_ahead + add_num + part_behind
print('插入数字6之后,新的字符串为:{}'.format(tmp_modified))
add_content_after_keyword()
这里需要关注一下注释,注释说明了part_ahead 和 part_behind的索引为什么需要加上len(add_num)
运行结果:
数字5在字符串tmp中的位置是:4
字符串前半部分切片的值是:12345
字符串后半部分切片的值是:78
插入数字6之后,新的字符串为:12345678
Process finished with exit code 0
那么对于复杂的处理场景也是一样的,我们以修改nginx的配置文件举例说明:
需求:
在nginx.conf的server块中加入一段配置,使得用户能通过nginx来访问静态资源
待处理的nginx.conf文件内容:
user root;
worker_processes 2;
worker_rlimit_nofile 2048;
events {
use epoll;
worker_connections 1024;
}
http {
include mime.types;
access_log /opt/logs/nginx/access.log main;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
server {
listen 8081;
server_name localhost;
charset utf-8;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 8082;
server_name localhost;
charset utf-8;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include /opt/nginx/conf.d/*.conf;
}
需要添加的配置:
location ^~ /static {
root /opt/application/;
index index.htm index.html;
try_files $uri $uri/ /static/index.html;
}
首先我们需要确定一个关键字,就是在nginx.conf中的哪个关键字之后加入我们需要的配置,这里我们将关键字选定为nginx.conf中的“charset utf-8;”
这个示例中展示了有多个关键字的情况,特意加了8081和8082两个server块。
代码:
import re
def add_nginx_conf(file_path):
with open(file_path, 'r') as r:
# 定义匹配关键字,注意这里如果有正则里面的需要转义的字符,要做对应的转义
keyword_matching = ' charset utf-8;'
content = r.read()
# 这里考虑了需要匹配多个相同的关键字,并且插入多段配置的情况,这行代码的作用是获取待处理的文本中有几处这样的关键字
keyword_rate = len([m.start() for m in re.finditer(keyword_matching, content)])
# 定义准备添加的文本
add_line = """ location ^~ /static {
\n root /opt/application/;
\n index index.htm index.html;
\n try_files $uri $uri/ /static/index.html;
\n }\n"""
for i in range(keyword_rate):
# 获取匹配到的关键字对应的索引值
index = [m.start() for m in re.finditer(keyword_matching, content)][i]
# 在每一处匹配到的关键字下方插入相关的配置。
content = content[:index] + add_line + content[index:]
with open(file_path, 'w') as w:
w.write(content)
add_nginx_conf('/opt/tmp/nginx.conf')
代码运行之后nginx.conf的内容;
user root;
worker_processes 2;
worker_rlimit_nofile 2048;
events {
use epoll;
worker_connections 1024;
}
http {
include mime.types;
access_log /opt/logs/nginx/access.log main;
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 9;
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
server {
listen 8081;
server_name localhost;
location ^~ /static {
root /opt/application/;
index index.htm index.html;
try_files $uri $uri/ /static/index.html;
}
charset utf-8;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
server {
listen 8082;
server_name localhost;
location ^~ /static {
root /opt/application/;
index index.htm index.html;
try_files $uri $uri/ /static/index.html;
}
charset utf-8;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
include /opt/nginx/conf.d/*.conf;
}
三、删除文件中指定的内容
删除文件中指定的内容同样可以通过切片来实现,但是实际操作中并不建议采取切片的方式,原因是只有在精确匹配待删除内容的情况下,通过切片操作才能正确实现删除需求。
而如果待删除内容中有大量正则表达式时,匹配工作就变得复杂且容易出错。
这里我们来介绍一下除了切片以外的方法:
先看一个简单的例子:
未完待续