我正在尝试用一个正则表达式匹配几种不同的文件名语法。换句话说,我试图将文件名字符串与相同字符以不同顺序进行匹配。问题是我不知道如何将“或”串在一起。分组方面的情况。
组语法:
文件名遵循以下模式:
PAF PA是产品类型的符号,Sheet#是无用的信息,FG#,RD#,X#,A#或#都是产品版本。我需要将产品名称,符号和修订号全部包含在自己的组中。
^(\w(?:\w*(?:-|\s|_)?\w+)*)
(?:
(-(?:FG|RD|X|A|)\d+)|
(-PA(?:F|)-\d+)(-(?:FG|RD|X|A|)\d+)|
(-PA(?:F|)-\d+)(?:(?:\s|-)sheet(?:\s|-)\d+)|
(-PA(?:F|)-\d+)(?:(?:\s|-)sheet(?:\s|-)\d+)(-(?:FG|RD|X|A|)\d+)
)
(?:.*)?$
我已经尝试了上述正则表达式,但无法正常工作。首先,它返回了太多的组,我只想要3。
pattern = re.compile(r'''^(\w(?:\w*(?:-|\s|_)?\w+)*) # match any alphanumeric and dashes without leading or trailing dashes
(-PA(?:F|)-\d+) # match '-PAF-<number>' or '-PA-<number>'
(?:(?:\s|-|)?sheet(?:\s|-|)?\d+)? # match '?sheet?<number>' where ? can be <space> or '-'
(-(?:FG|RD|X|A|)\d+)? # match '-FG<number>', '-RD<number>', '-X<number>', '-A<number>' or <number>
(?:.*)?$''', flags=re.IGNORECASE|re.VERBOSE)
上述字符串应与正则表达式匹配。
答案 0 :(得分:1)
在新示例后进行编辑
为避免使正则表达式模式过于复杂(这已经足够了),我将首先去除“工作表”部分。
因此,首先,在应用匹配指令之前,从文件名中删除“ sheet#”模式。
这只会将您的情况减少为以下几种方式:
(产品名称)-(PAF / PA-#)-(修订版)
(产品名称)-(修订)
然后将正则表达式分成三组。 对于修订组,我使用了(?!...)否定的超前断言来处理以下情况:“ 2400PSUA-8-PA-1-X0”
这是修改后的代码:
import re
string = """10G-HUB-PAF-1 Sheet 1-FG0
HUB-DISP-SPCR-RD0
HUB-MAIN-PA-1-FG0
2400ODU-PA-1-X0 Sheet 1
2400PSUA-8-PA-1-Sheet1-X0
2405OE-PAF-1-FG0
2400PSUA-8-PA-1-Sheet1-X0
XXXX-XXX-123-PAF-1-FG0 Sheet 1
"""
regex = r'(?# product name )(.*?)' + \
r'(?# PA|PAF )(?:(?:-)(?:(PAF-\d|PA-\d).*))?' + \
r'(?# Revision )(?:-)((?:\d)(?!.*(?:FG|RD|X|A\d))|(?:(?:FG|RD|X|A)\d))'
pattern = re.compile(regex, flags=re.IGNORECASE|re.VERBOSE)
for s in string.splitlines():
print('String %s' % s)
# Remove 'Sheet#' or 'Sheet #' or '-Sheet #' or '-Sheet#'
s=re.sub(r'-?sheet\s?\d','',s, flags=re.IGNORECASE)
print('Purged string: %s' % s)
f=pattern.match(s)
print('group1: %s' % f.group(1))
print('group2: %s' % f.group(2))
print('group3: %s\n' % f.group(3))
有一些输出:
String 10G-HUB-PAF-1 Sheet 1-FG0
Purged string: 10G-HUB-PAF-1 -FG0
group1: 10G-HUB
group2: PAF-1
group3: FG0
String HUB-DISP-SPCR-RD0
Purged string: HUB-DISP-SPCR-RD0
group1: HUB-DISP-SPCR
group2: None
group3: RD0
...omitted output ...
String 2400PSUA-8-PA-1-Sheet1-X0
Purged string: 2400PSUA-8-PA-1-X0
group1: 2400PSUA-8
group2: PA-1
group3: X0
String XXXX-XXX-123-PAF-1-FG0 Sheet 1
Purged string: XXXX-XXX-123-PAF-1-FG0
group1: XXXX-XXX-123
group2: PAF-1
group3: FG0
答案 1 :(得分:0)
在使用正则表达式进行了很多练习之后,并在GDN的帮助下,我找到了解决方案:
(.*?)(?:(?:\s|_|-|\s?-\s|\s-\s?)(?=(?:PAF-|PA-|FG|RD|X|A)\d+))((?:PAF|PA)-\d+)?(?:\s|_|-|\s?-\s|\s-\s?)?(?:.*?)?((?:FG|RD|X|A)\d+)
import re
def input_loop(pattern, doc_type):
while True:
filename = raw_input('Enter {}, Enter "x" to Close: '.format(doc_type))
if filename == 'x':
break
matches = pattern.match(filename)
if matches:
groups = matches.groups()
print groups
else:
print '''Couldn't match string: "{}"'''.format(filename)
pattern = re.compile(r'''
(.*?)(?# Match product name)
(?:(?:\s|_|-|\s?-\s|\s-\s?)(?=(?:PAF-|PA-|FG|RD|X|A)\d+))(?# Match spacer after product name)
((?:PAF|PA)-\d+)?(?# Match optional PAF-# or PA-#)
(?:\s|_|-|\s?-\s|\s-\s?)?(?# Match spacer after product type name)
(?:.*?)?(?# Match useless data)
((?:FG|RD|X|A)\d+)''', flags=re.IGNORECASE|re.VERBOSE)
input_loop(pattern, 'Assembly Drawings')