如何在Python中用正则表达式提取字符串中的ID和DIRECTION字段?
基于命名规则用正则表达式提取ID和DIRECTION字段
需求说明
- 从查询字符串中提取ID和DIRECTION两个字段:
- DIRECTION的值仅能是
1或2; - ID可以是文件系统允许的任意字符串(如字母数字、
-、_、.)。
- DIRECTION的值仅能是
- 计划实现的函数框架如下:
def extract_fields(query: str, naming_scheme: str): # 实现代码 return (ID, DIRECTION)
测试示例
命名规则1
naming_scheme_1 = "[ID]_R[DIRECTION].fastq.gz" # 测试用例1 ID, DIRECTION = extract_fields("Kuwait_110_S59_R1.fastq.gz", naming_scheme_1) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "1" # 测试用例2 ID, DIRECTION = extract_fields("Kuwait_110_S59_R2.fastq.gz", naming_scheme_1) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "2"
命名规则2
naming_scheme_2 = "[ID]_R[DIRECTION]_001.fastq.gz" # 测试用例1 ID, DIRECTION = extract_fields("Kuwait_110_S59_R1_001.fastq.gz", naming_scheme_2) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "1" # 测试用例2 ID, DIRECTION = extract_fields("Kuwait_110_S59_R2_001.fastq.gz", naming_scheme_2) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "2"
命名规则3
naming_scheme_3 = "barcode-[ID]_[DIRECTION].fq" # 测试用例1 ID, DIRECTION = extract_fields("barcode-Kuwait_110_S59_1.fq", naming_scheme_3) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "1" # 测试用例2 ID, DIRECTION = extract_fields("barcode-Kuwait_110_S59_2.fq", naming_scheme_3) # 预期结果:ID = "Kuwait_110_S59",DIRECTION = "2"
当前问题
之前尝试用多次字符串拆分的方式实现,但效果不佳,希望用正则表达式完成该需求。
解决方案
核心思路是把自定义的命名规则转换成正则表达式,将[ID]和[DIRECTION]替换为对应的捕获组,同时转义命名规则中的正则特殊字符(如.)。
实现代码如下:
import re def extract_fields(query: str, naming_scheme: str): # 用临时占位符替换[ID]和[DIRECTION],避免转义正则特殊字符时被误处理 temp_scheme = naming_scheme.replace("[ID]", "__ID_PLACEHOLDER__") temp_scheme = temp_scheme.replace("[DIRECTION]", "__DIR_PLACEHOLDER__") # 转义命名规则中的正则特殊字符 escaped_scheme = re.escape(temp_scheme) # 替换回对应的正则捕获组 regex_pattern = escaped_scheme.replace("__ID_PLACEHOLDER__", "(?P<ID>[\\w\\-.]+)") regex_pattern = regex_pattern.replace("__DIR_PLACEHOLDER__", "(?P<DIRECTION>[12])") # 加上首尾锚点,确保查询字符串完全匹配命名规则 regex_pattern = f"^{regex_pattern}$" match = re.match(regex_pattern, query) if not match: raise ValueError(f"查询字符串 {query} 不符合命名规则 {naming_scheme}") return (match.group("ID"), match.group("DIRECTION"))
验证测试
运行以下代码验证效果:
# 测试命名规则1 naming_scheme_1 = "[ID]_R[DIRECTION].fastq.gz" print(extract_fields("Kuwait_110_S59_R1.fastq.gz", naming_scheme_1)) # 输出: ('Kuwait_110_S59', '1') print(extract_fields("Kuwait_110_S59_R2.fastq.gz", naming_scheme_1)) # 输出: ('Kuwait_110_S59', '2') # 测试命名规则2 naming_scheme_2 = "[ID]_R[DIRECTION]_001.fastq.gz" print(extract_fields("Kuwait_110_S59_R1_001.fastq.gz", naming_scheme_2)) # 输出: ('Kuwait_110_S59', '1') print(extract_fields("Kuwait_110_S59_R2_001.fastq.gz", naming_scheme_2)) # 输出: ('Kuwait_110_S59', '2') # 测试命名规则3 naming_scheme_3 = "barcode-[ID]_[DIRECTION].fq" print(extract_fields("barcode-Kuwait_110_S59_1.fq", naming_scheme_3)) # 输出: ('Kuwait_110_S59', '1') print(extract_fields("barcode-Kuwait_110_S59_2.fq", naming_scheme_3)) # 输出: ('Kuwait_110_S59', '2')
代码说明
- 临时占位符替换:先把
[ID]和[DIRECTION]换成临时字符串,避免在转义正则特殊字符时被误处理; - 正则转义:用
re.escape()转义命名规则中的特殊字符(比如.会被转义成\.,确保匹配实际的点号); - 捕获组定义:
(?P<ID>[\\w\\-.]+):匹配ID允许的所有字符(字母数字、下划线、连字符、点号);(?P<DIRECTION>[12]):仅匹配1或2;
- 完全匹配校验:给正则表达式加上
^和$,确保查询字符串完全符合命名规则,避免部分匹配导致的错误。
内容的提问来源于stack exchange,提问作者O.rka
相关产品推荐
相关产品推荐

