基本上,我有一个包含英语语句的数据集。有些语句包含前导/尾随标点符号,所以我想清理和标准化它们。标准化的标准是删除所有前导/尾随标点符号,语句的第一个字符大写,并且语句以句点结尾。我有一个函数可以执行此操作并将其应用于数据集中的每一行。
如果有帮助的话,这里是一个代码片段:
def normalize_statement(statement):
# remove leading/trailing punctuation and excess whitespace
cleaned = statement.strip(whitespace + punctuation)
cleaned = re.sub(r'\s+', ' ', cleaned)
# capitalize first letter
cleaned = cleaned[0].upper() + cleaned[1:]
# ensure the statement ends with a period
if cleaned and not cleaned.endswith('.'):
cleaned += '.'
return cleaned
此函数适用于基本语句,但并不总是适用于 double 或 之间包裹的子字符串单引号,特别是当带引号的子字符串出现在语句的开头和/或结尾时,因为在删除前导标点符号后,其中一个引号会被删除(即
'"this" is a statement'
将成为
'This" is a statement'
)。目的应该是在清理后保留任何子字符串周围的引号。
我考虑过使用正则表达式来捕获单引号或双引号之间的所有子字符串,用捕获的组替换所有带引号的子字符串以删除引号,标准化语句,然后将引用的子字符串添加回其原始位置。这是更新后的函数:
def normalize_statement(statement):
# extract any and all substrings enclosed in quotation marks
quoted_pattern = re.compile(r'["\'](.*?)["\']')
quoted_substrings = quoted_pattern.findall(statement)
# replace the quoted substrings with the captured groups
cleaned = re.sub(quoted_pattern, lambda m: m.group(1), statement)
# remove leading/trailing punctuation and excess whitespace
cleaned = cleaned.strip(whitespace + punctuation)
cleaned = re.sub(r'\s+', ' ', cleaned)
# capitalize first letter for languages that use capitalization
cleaned = cleaned[0].upper() + cleaned[1:]
# ensure the statement ends with a period
if cleaned and not cleaned.endswith('.'):
cleaned += '.'
# replace quoted substrings (if any) back into their original positions after cleaning
for quoted_substring in quoted_substrings:
cleaned = re.sub(re.escape(quoted_substring.strip(whitespace + punctuation)), f'\"{quoted_substring}\"', cleaned, flags=re.IGNORECASE)
return cleaned
虽然正则表达式模式
["\'](.*?)["\']
有时有效(即“期望”员工拥抱“节俭”。),但对于“没有像家这样的地方,强调独特的舒适度”这样的陈述,它会失败自己周围的环境。因为在这种情况下捕获的组将是撇号之间的子字符串:“没有像家一样的地方,强调一个人的独特舒适感”。
我只想捕获引号之间的文本 - 但如何区分撇号和我的正则表达式模式中的单引号?我对正则表达式不太熟悉,所以如果有人有不同的方法,将不胜感激!
当然可以!可以修改正则表达式以仅匹配单引号,而不是撇号。以下是一种方法:
import re
def normalize_statement(statement):
# 使用以下正则表达式匹配单引号之间的子字符串,而忽略撇号
quoted_pattern = re.compile(r"(?<!\w)'(.*?)'(?!\w)")
quoted_substrings = quoted_pattern.findall(statement)
# 将引用的子字符串替换为占位符,以保留它们在清理过程中的位置
for i, quoted_substring in enumerate(quoted_substrings):
statement = statement.replace(quoted_substring, f"__placeholder_{i}__")
# 删除前导/尾随标点符号和多余的空白
cleaned = statement.strip(whitespace + punctuation)
cleaned = re.sub(r'\s+', ' ', cleaned)
# 将第一个字母大写
cleaned = cleaned[0].upper() + cleaned[1:]
# 确保语句以句点结尾
if cleaned and not cleaned.endswith('.'):
cleaned += '.'
# 将引用的子字符串放回其原始位置
for i, quoted_substring in enumerate(quoted_substrings):
cleaned = cleaned.replace(f"__placeholder_{i}__", f"'{quoted_substring}'")
return cleaned
正则表达式的解释:
-
(?<!\w)
:这是一个负向回溯断言,它确保单引号 ('
) 前面没有字母数字字符 (\w
)。这有助于排除撇号,因为撇号通常出现在单词中。 -
'
:这与一个单引号匹配。 -
(.*?)
:这与任何字符匹配零次或多次,非贪婪,并将匹配项捕获到组 1 中。 -
'
:这与另一个单引号匹配。 -
(?!\w)
:这是一个正向断言,它确保单引号 ('
) 后面没有字母数字字符 (\w
)。这也有助于排除撇号。
通过使用此改进的正则表达式,的代码将仅提取由单引号包围的子字符串,而忽略用作撇号的单引号。让我们知道这对是否有效!
标签:python,regex,text From: 78819189