如何筛选指定前缀的.shp文件列表?解决数字前缀匹配歧义
精准匹配1-12开头的.shp文件列表问题解决
问题说明
- 需求:为以1-12开头且后缀为
.shp的文件分别生成独立列表 - 初始代码报错:
AttributeError: 'list' object has no attribute 'endswith' - 优化后代码缺陷:匹配前缀“1”时,会错误包含以“10”“11”“12”开头的
.shp文件
初始报错代码
from os.path import normpath import os path_temp2 = normpath(r'C:\Users\tlind\Dropbox\Documents\Temp\temp2layers\') merge_list = os.listdir(path_temp2) for i in range(1,13): test = [] check = str(i) res = [idx for idx in merge_list if idx.lower().startswith(check.lower())] test.append(res) for file in test: test2 = [] if file.endswith('.shp'): test2.append(file) print(test2)
存在匹配缺陷的代码
from os.path import normpath import os path_temp2 = normpath(r'C:\Users\tlind\Dropbox\Documents\Temp\temp2layers\') merge_list = os.listdir(path_temp2) for i in range(1,13): check = str(i) name_ext_matches = [] name_matches = [idx for idx in merge_list if idx.lower().startswith(check.lower())] for file in name_matches: if file.endswith('.shp'): name_ext_matches.append(file) print(name_ext_matches)
解决方案
问题根源
startswith方法会匹配所有以目标字符串开头的内容,比如“1”会匹配“10xxx.shp”这类文件名,无法区分单个数字和多位数前缀。需要精准验证前缀是独立的1-12,而非更长数字的开头。
方案1:正则表达式精准匹配
用正则规则确保前缀是目标数字,且之后的字符不是数字(或直接接.shp后缀):
from os.path import normpath import os import re path_temp2 = normpath(r'C:\Users\tlind\Dropbox\Documents\Temp\temp2layers\') merge_list = os.listdir(path_temp2) for i in range(1, 13): check = str(i) # 正则规则:以check开头,后续要么是非数字字符,要么直接到.shp结尾 pattern = re.compile(f'^{re.escape(check)}(?:\\D|\\.shp$)', re.IGNORECASE) matched_files = [] for file in merge_list: if file.endswith('.shp') and pattern.match(file): matched_files.append(file) print(f"前缀{i}对应的.shp文件: {matched_files}")
方案2:拆分文件名验证
提取文件名(不含后缀),检查前缀部分完全等于目标数字,且后续字符非数字:
from os.path import normpath, splitext import os path_temp2 = normpath(r'C:\Users\tlind\Dropbox\Documents\Temp\temp2layers\') merge_list = os.listdir(path_temp2) for i in range(1, 13): check = str(i) matched_files = [] for file in merge_list: if file.endswith('.shp'): filename = splitext(file)[0] # 截取和check长度一致的前缀,确认匹配,且剩余部分要么为空要么首字符不是数字 if len(filename) >= len(check): prefix = filename[:len(check)] rest = filename[len(check):] if prefix == check and (not rest or not rest[0].isdigit()): matched_files.append(file) print(f"前缀{i}对应的.shp文件: {matched_files}")
初始报错原因
初始代码里test.append(res)将列表res嵌套进test,导致后续循环中file是列表类型,而列表没有endswith方法,因此抛出AttributeError。优化后的代码去掉了不必要的嵌套,解决了报错,但未处理前缀匹配精度问题。
内容的提问来源于stack exchange,提问作者Tobias Bowley
相关产品推荐
相关产品推荐

