Python如何强制一个字符串匹配另一个字符串的格式

Python如何强制一个字符串匹配另一个字符串的格式,python,regex,string,python-2.7,formatting,Python,Regex,String,Python 2.7,Formatting,我有一些为我工作的评估员办公室编写的Python脚本。其中大多数要求输入地块ID号(然后通过odbc获取特定数据)。他们输入包裹ID的方式不太一致 这就是我的问题,他们通过以下三种方式之一输入地块ID: 1:'1005191000060' 2:'001005191000060' 3:'0010-05-19-100-006-0' 第三种方法是正确的方法,因此我需要确保输入是固定的,以始终匹配该格式。当然,他们宁愿输入前两种方式之一的ID。地块编号必须始终为15位(20位带破折号) 我目前有一个关于

我有一些为我工作的评估员办公室编写的Python脚本。其中大多数要求输入地块ID号(然后通过odbc获取特定数据)。他们输入包裹ID的方式不太一致

这就是我的问题,他们通过以下三种方式之一输入地块ID:

1:'1005191000060'

2:'001005191000060'

3:'0010-05-19-100-006-0'

第三种方法是正确的方法,因此我需要确保输入是固定的,以始终匹配该格式。当然,他们宁愿输入前两种方式之一的ID。地块编号必须始终为15位(20位带破折号)

我目前有一个关于如何修复地块ID的工作方法,但它非常难看。我想知道是否有人知道一个更好的方法(或者更“Pythonic”的方法)。我有一个函数,通常被导入到所有这些脚本中。以下是我所拥有的:

import re

def FormatPID(in_pid):
    pid_format = re.compile('\d{4}-\d{2}-\d{2}-\d{3}-\d{3}-\d{1}')
    pid = in_pid.zfill(15) 
    if not pid_format.match(pid):
        fixed_pid = '-'.join([pid[:4],pid[4:6],pid[6:8],pid[8:11],pid[11:-1],pid[-1]])
        return fixed_pid
    else:
        return pid

if __name__ == '__main__':

    pid = '1005191000060'
##    pid = '001005191000060'
##    pid = '0010-05-19-100-006-0'

    # test
    t = FormatPID(pid)
    print t

这确实工作得很好,但我已经被这段丑陋的代码困扰了一段时间,我想一定有比切片更好的方法。我希望有一种方法可以“强制”将其转换为字符串以匹配“pid_格式”变量。有什么想法吗?我在正则表达式模块中找不到任何可以执行此操作的方法,您可以使用
itertools.islice
代替手动切片:

import re
from itertools import islice
groups = (4, 2, 2, 3, 3, 1)
def FormatPID(in_pid):
    pid_format = re.compile('\d{4}-\d{2}-\d{2}-\d{3}-\d{3}-\d{1}')
    in_pid = in_pid.zfill(15)
    if not pid_format.match(in_pid):
        it = iter(in_pid)
        return '-'.join(''.join(islice(it, i)) for i in groups)
    return in_pid

print FormatPID('1005191000060')
print FormatPID('001005191000060')
print FormatPID('0010-05-19-100-006-0')
输出:

0010-05-19-100-006-0
0010-05-19-100-006-0
0010-05-19-100-006-0

我不会费心使用正则表达式。你只想得到所有的数字,忽略连字符,左边填充0,然后在正确的位置插入连字符,对吗?因此:

def format_pid(pid):
    p = pid.replace('-', '')
    if not p.isdigit():
        raise ValueError('Invalid format: {}'.format(pid))
    p = p.zfill(15)
    # You can use your `join` call instead of the following if you prefer.
    # Or Ashwini's islice call.
    return '{}-{}-{}-{}-{}-{}'.format(p[:4], p[4:6], p[6:8], p[8:11], p[11:14], p[14:])

我认为他不想做任何填充,他希望他们输入准确的数字,然后将破折号插入适当的位置。@EricAmorde:如果他不想做任何填充,示例1将如何工作?谢谢abarnert。不过,我想我会坚持埃里克的回答。我想摆脱“丑陋的切片”。这和我原来的帖子没什么不同。尽管如此,我还是喜欢使用isdigit()而不是我的正则表达式。我对“\d”的使用不会做同样的事情吗?文档说明:\d未指定UNICODE标志时,匹配任何十进制数字;这相当于集合[0-9]。使用UNICODE,它将匹配UNICODE字符属性数据库中分类为十进制数字的任何内容。@cmackey:嗯,
isdigit()
将执行与显式编写的正则表达式相同的操作,以表示与
isdigit()
相同的操作。这将更简单、更快,更难出错。但请注意,您的代码假设要么所有连字符都在正确的位置,要么只有数字;我的代码是检查你是否只有数字或连字符,忽略连字符,然后使用数字。很好…我试图找到与此类似的东西。我只是讨厌看我正在做的丑陋的切片手术。非常感谢你!