加入来自 python-docx 的运行,以便将正则表达式应用于运行组
Join runs from python-docx for the purpose of applying regex to group of runs
我正在使用 Python-Docx 来阅读 docx 文件,找到特定的字符串(例如日期),并将其替换为另一个字符串(例如新日期)。
这是我正在使用的两个函数:
def docx_replace_regex(doc_obj, regex , replace):
for p in doc_obj.paragraphs:
if regex.search(p.text):
inline = p.runs
# Loop added to work with runs (strings with same style)
for i in range(len(inline)):
if regex.search(inline[i].text):
text = regex.sub(replace, inline[i].text)
inline[i].text = text
for table in doc_obj.tables:
for row in table.rows:
for cell in row.cells:
docx_replace_regex(cell, regex , replace)
def replace_date(folder,replaceDate,*date):
docs = [y for x in os.walk(folder) for y in glob(os.path.join(x[0], '*.docx'))]
for doc in docs:
if date: #Date is optional date to replace
regex = re.compile(r+date)
else: #If no date provided, replace all dates
regex = re.compile(r"(\w{3,12}\s\d{1,2}\,?\s?[0-9]{4})|((the\s)?\d{1,2}[th]{0,2}\sday\sof\s\w{3,12}\,\s?\d{4})")
docObj = Document(doc)
docx_replace_regex(docObj,regex,replaceDate)
docObj.save(doc)
第一个函数本质上是一个查找和替换函数,用于 python docx 文件。第二个文件通过文件路径递归搜索以查找要搜索的 docx 文件。正则表达式的细节不相关(我认为)。它本质上是搜索不同的日期格式。它按我的意愿工作,不应影响我的问题。
当文档传递给 docx_replace_regex 时,该函数遍历段落,然后 运行s 并在 运行s 中搜索我的正则表达式。问题是 运行s 有时会分解单行文本,因此如果文档是明文,则正则表达式会捕获文本,但由于 运行s 会分解文本,因此文本没有被捕获。
例如,如果我的段落是“2020 年 5 月 10 日”,则内联数组可能是 ['1','0th day of May,',' 2020']
.
最初,我加入了内联数组,使其等于“2020 年 5 月 10 日”,但后来我无法用新文本替换 运行,因为我的内联变量是字符串,而不是 运行 对象。即使我将内联保持为 运行 对象,它仍然只会替换我要查找的文本的一部分。
寻找有关如何正确替换由我的正则表达式捕获的文本部分的任何想法。或者,为什么句子按原样被分解成单独的 运行s。
这不是一个简单的问题,看来你开始意识到了:)
最简单的方法是在 paragraph.text
中搜索和替换,例如:
paragraph.text = my_replace_function(paragraph.text, ...)
这有效,但所有字符格式都丢失了。一种更复杂的方法是找到搜索短语的偏移量,将其映射到运行,然后根据需要拆分和重新加入运行以仅更改包含搜索短语的那些运行。
这里似乎有一个可行的解决方案:,它的长度显示了涉及的内容。
它以前出现过好几次,所以如果你在 [python-docx] replace
上的 SO 中搜索,你会发现更多关于问题本质的信息。
我正在使用 Python-Docx 来阅读 docx 文件,找到特定的字符串(例如日期),并将其替换为另一个字符串(例如新日期)。
这是我正在使用的两个函数:
def docx_replace_regex(doc_obj, regex , replace):
for p in doc_obj.paragraphs:
if regex.search(p.text):
inline = p.runs
# Loop added to work with runs (strings with same style)
for i in range(len(inline)):
if regex.search(inline[i].text):
text = regex.sub(replace, inline[i].text)
inline[i].text = text
for table in doc_obj.tables:
for row in table.rows:
for cell in row.cells:
docx_replace_regex(cell, regex , replace)
def replace_date(folder,replaceDate,*date):
docs = [y for x in os.walk(folder) for y in glob(os.path.join(x[0], '*.docx'))]
for doc in docs:
if date: #Date is optional date to replace
regex = re.compile(r+date)
else: #If no date provided, replace all dates
regex = re.compile(r"(\w{3,12}\s\d{1,2}\,?\s?[0-9]{4})|((the\s)?\d{1,2}[th]{0,2}\sday\sof\s\w{3,12}\,\s?\d{4})")
docObj = Document(doc)
docx_replace_regex(docObj,regex,replaceDate)
docObj.save(doc)
第一个函数本质上是一个查找和替换函数,用于 python docx 文件。第二个文件通过文件路径递归搜索以查找要搜索的 docx 文件。正则表达式的细节不相关(我认为)。它本质上是搜索不同的日期格式。它按我的意愿工作,不应影响我的问题。
当文档传递给 docx_replace_regex 时,该函数遍历段落,然后 运行s 并在 运行s 中搜索我的正则表达式。问题是 运行s 有时会分解单行文本,因此如果文档是明文,则正则表达式会捕获文本,但由于 运行s 会分解文本,因此文本没有被捕获。
例如,如果我的段落是“2020 年 5 月 10 日”,则内联数组可能是 ['1','0th day of May,',' 2020']
.
最初,我加入了内联数组,使其等于“2020 年 5 月 10 日”,但后来我无法用新文本替换 运行,因为我的内联变量是字符串,而不是 运行 对象。即使我将内联保持为 运行 对象,它仍然只会替换我要查找的文本的一部分。
寻找有关如何正确替换由我的正则表达式捕获的文本部分的任何想法。或者,为什么句子按原样被分解成单独的 运行s。
这不是一个简单的问题,看来你开始意识到了:)
最简单的方法是在 paragraph.text
中搜索和替换,例如:
paragraph.text = my_replace_function(paragraph.text, ...)
这有效,但所有字符格式都丢失了。一种更复杂的方法是找到搜索短语的偏移量,将其映射到运行,然后根据需要拆分和重新加入运行以仅更改包含搜索短语的那些运行。
这里似乎有一个可行的解决方案:
它以前出现过好几次,所以如果你在 [python-docx] replace
上的 SO 中搜索,你会发现更多关于问题本质的信息。