我在自动化脚本中使用了一些大型文本文件来进行音频调整。文本文件中的每一行看起来大致如下:
A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]] BANANA # BANANA
文本被送到一个旧的命令行程序,该程序搜索关键字并将它们交换出来。样本输出将是:
A[0] + B[100] - C[0x1000] [[0]] 0 # 0
A[2] + B[200] - C[0x100A] [[2]] 0 # 0
有时,文本文件中的关键字应保持不变(即我们不希望“BANANA”替换的情况)。我想修改文本文件以使用某种在正常情况下不太可能弹出的关键字/分隔符,即:
A[#1] + B[#2] - C[#3] [[#1]] #1 # #1
python的文本文件解析器是否有我可以使用的特殊索引/转义序列而不是简单的关键字?
答案 0 :(得分:2)
您可以使用re.sub
执行替换。这个答案会创建一个随机值列表来演示,但是,列表可以替换为您正在使用的数据:
import re
import random
s = "A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]"
new_s = re.sub('(?<=\[)[a-zA-Z0-9]+(?=\])', '{}', s)
random_data = [[random.randint(1, 2000) for i in range(4)] for _ in range(10)]
final_results = [new_s.format(*i) for i in random_data]
for command in final_results:
print(command)
输出:
A[51] + B[134] - C[864] [[1344]]
A[468] + B[1761] - C[1132] [[1927]]
A[1236] + B[34] - C[494] [[1009]]
A[1330] + B[1002] - C[1751] [[1813]]
A[936] + B[567] - C[393] [[560]]
A[1926] + B[936] - C[906] [[1596]]
A[1532] + B[1881] - C[871] [[1766]]
A[506] + B[1505] - C[1096] [[491]]
A[290] + B[1841] - C[664] [[38]]
A[1552] + B[501] - C[500] [[373]]
答案 1 :(得分:2)
使用正则表达式替换函数和字典。
匹配括号之间的所有内容(非贪婪,避免使用括号本身)并替换为dict的值,如果找不到原始值,则放置原始值:
import re
d = {"BANANA":"12", "PINEAPPLE":"20","CHERRY":"100","BANANA":"400"}
s = "A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]"
print(re.sub("\[([^\[\]]*)\]",lambda m : "[{}]".format(d.get(m.group(1),m.group(1))),s))
打印:
A[400] + B[20] - C[100] [[400]]
答案 2 :(得分:1)
只需使用
\[([^][]+)\]
并将其替换为所需的结果,例如: 123
。
\[ # opening bracket
([^][]+) # capture anything not brackets, 1+ times
\] # closing bracket
<小时/>
对于您更改的要求,您可以使用OrderedDict
:
import re
from collections import OrderedDict
rx = re.compile(r'\[([^][]+)\]')
d = OrderedDict()
def replacer(match):
item = match.group(1)
d[item] = 1
return '[#{}]'.format(list(d.keys()).index(item) + 1)
string = "A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]"
string = rx.sub(replacer, string)
print(string)
哪个收益
A[#1] + B[#2] - C[#3] [[#1]]
这里的想法是将每个(可能的)新项目放入dict中,然后搜索索引。 OrderedDict
记住订单输入。
import re
class Replacer:
rx = re.compile(r'\[([^][]+)\]')
keywords = []
def do_replace(self, match):
idx = self.lookup(match.group(1))
return '[#{}]'.format(idx + 1)
def replace(self, string):
return self.rx.sub(self.do_replace, string)
def lookup(self, item):
for idx, key in enumerate(self.keywords):
if key == item:
return idx
self.keywords.append(item)
return len(self.keywords)-1
string = "A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]"
rpl = Replacer()
string = rpl.replace(string)
print(string)
答案 3 :(得分:1)
也可以使用pyparsing完成。
这个解析器实质上将noun
定义为方括号内的大写字母,然后将它们的序列定义为一行输入,如complete
。
要使用其他内容替换标识的项目,请以合适的方式定义class
dict
,以便class
以外的任何内容保持不变。
>>> import pyparsing as pp
>>> noun = pp.Word(pp.alphas.upper())
>>> between = pp.CharsNotIn('[]')
>>> leftbrackets = pp.OneOrMore('[')
>>> rightbrackets = pp.OneOrMore(']')
>>> stmt = 'A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]'
>>> one = between + leftbrackets + noun + rightbrackets
>>> complete = pp.OneOrMore(one)
>>> complete.parseString(stmt)
(['A', '[', 'BANANA', ']', ' + B', '[', 'PINEAPPLE', ']', ' - C', '[', 'CHERRY', ']', ' ', '[', '[', 'BANANA', ']', ']'], {})
>>> class Replace(dict):
... def __missing__(self, key):
... return key
...
>>> replace = Replace({'BANANA': '1', 'PINEAPPLE': '2'})
>>> new = []
>>> for item in complete.parseString(stmt).asList():
... new.append(replace[item])
...
>>> ''.join(new)
'A[1] + B[2] - C[CHERRY] [[1]]'
答案 4 :(得分:1)
我认为使用plex更容易 - 也更清晰。问题在于它似乎仅适用于Py2。我花了一两个小时才把足够的转换工作交给Py3来实现。
只需要注意三种类型的令牌,然后在while
语句中使用相同数量的分支。
from plex import *
from io import StringIO
stmt = StringIO('A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]')
lexicon = Lexicon([
(Rep1(AnyBut('[]')), 'not_brackets'),
(Str('['), 'left_bracket'),
(Str(']'), 'right_bracket'),
])
class Replace(dict):
def __missing__(self, key):
return key
replace = Replace({'BANANA': '1', 'PINEAPPLE': '2'})
scanner = Scanner(lexicon, stmt)
new_statement = []
while True:
token = scanner.read()
if token[0] is None:
break
elif token[0]=='no_brackets':
new_statement.append(replace[token[1]])
else:
new_statement.append(token[1])
print (''.join(new_statement))
结果:
A[BANANA] + B[PINEAPPLE] - C[CHERRY] [[BANANA]]