조쉬 캐스 웰은 숀 밝은의 대답은 원래 그룹보다 더 많은 입력을 일치 지적했다. 미안해. 이걸 알아 내지 못했어. (장래에 문제를 조금 더 자세히 설명하는 것이 좋습니다.)
그래서 기본적인 문제는 중요하지 않다는 것입니다. 그러나 우리는 여전히 매우 매끄러운 방식으로 파이썬에서이를 해결할 수 있습니다. 먼저 법적인 입력 내용과 일치하는 패턴을 만들지 만 거부하려는 패턴과 일치시킵니다.
다음으로 패턴을 사용하는 함수를 정의한 다음 일치 객체를 검사하고 일치하는 문자열이 길이 요구 사항을 충족하는지 확인합니다.
import re
_s_pat = r'([A-Z]{1,2})(\d{1,3})-([A-Z]{1,2})(\d{1,3})'
_pat = re.compile(_s_pat)
_valid_n_len = set([(1,1), (1,2), (1,3), (2,2), (2,3), (3,3)])
def check_match(s):
m = _pat.search(s)
try:
a0, n0, a1, n1 = m.groups()
if len(a0) != len(a1):
return False
if not (len(n0), len(n1)) in _valid_n_len:
return False
return True
except (AttributeError, TypeError, ValueError):
return False
다음은 위의 코드에 대한 설명입니다.
먼저 패턴을 정의하기 위해 원시 문자열을 사용하고 패턴을 미리 컴파일합니다. 우리는 re.compile()
에 대한 호출에 리터럴 문자열을 채울 수는 있지만 별도의 문자열을 갖고 싶어합니다. 우리 패턴에는 괄호 안에 4 개의 뚜렷한 섹션이 있습니다. 이들은 "일치 그룹"이됩니다. 알파벳 문자와 일치하는 두 개의 일치 그룹과 숫자와 일치하는 두 개의 일치 그룹이 있습니다. 이 패턴은 당신이 원하는 모든 것을 일치 시키지만 원하지 않는 것들은 제외시키지 않을 것입니다.
다음으로 숫자에 대해 유효한 길이가 모두있는 set
을 선언합니다. 예를 들어, 첫 x 째 그룹은 1 자릿수이고 두 x 째 그룹은 2 자릿수가 될 수 있습니다. 이 값은 (1,2)
(tuple
값)입니다. 세트는 주어진 합당한 길이의 쌍이 합법적인지 신속하게 확인할 수있는 동시에 합법적 인 모든 가능한 조합을 지정하는 좋은 방법입니다.
함수 check_match()
은 문자열과 일치하는 패턴을 먼저 사용하여 m
이라는 이름으로 바인딩 된 "일치 개체"를 반환합니다. 검색에 실패하면 m
이 None
으로 설정 될 수 있습니다. 명시 적으로 None
을 테스트하는 대신 try
/except
블록을 사용했습니다. 되돌아 보면 None
을 테스트하는 것이 더 나았을 것입니다. 죄송합니다. 혼란 스러울 의도는 없었습니다. 그러나 try
/except
블록은 무언가를 랩핑하고 매우 신뢰할 수있게 만드는 아주 간단한 방법이므로, 나는 종종 이런 식으로 사용합니다.
마지막으로 check_match()
은 일치 그룹을 4 개의 변수로 압축 해제합니다. 두 개의 알파 그룹은 a0과 a1이고 두 개의 숫자 그룹은 n0과 n1입니다. 그런 다음 길이가 합법적인지 확인합니다. 내가 알 수있는 한, 규칙은 알파 그룹이 동일한 길이 일 필요가 있다는 것입니다. 번호 그룹 길이가 tuple
인 것을 확인하고 tuple
이 tuple
인 set
에 있는지 확인합니다.
위와 약간 다른 버전입니다. 어쩌면 당신은 그것을 더 좋아할 것입니다.
import re
# match alpha: 1 or 2 capital letters
_s_pat_a = r'[A-Z]{1,2}'
# match number: 1-3 digits
_s_pat_n = r'\d{1,3}'
# pattern: four match groups: alpha, number, alpha, number
_s_pat = '(%s)(%s)-(%s)(%s)' % (_s_pat_a, _s_pat_n, _s_pat_a, _s_pat_n)
_pat = re.compile(_s_pat)
# set of valid lengths of number groups
_valid_n_len = set([(1,1), (1,2), (1,3), (2,2), (2,3), (3,3)])
def check_match(s):
m = _pat.search(s)
if not m:
return False
a0, n0, a1, n1 = m.groups()
if len(a0) != len(a1):
return False
tup = (len(n0), len(n1)) # make tuple of actual lengths
if not tup in _valid_n_len:
return False
return True
참고 : 그것은 유효 길이에 대한 규칙처럼 보인다는 사실 간단하다 : 그 규칙이 당신을 위해 작동
if len(n0) > len(n1):
return False
경우, 세트와 튜플 물건을 제거 할 수있다. 흠, 나는 변수 이름을 좀 더 짧게 만들 것이다.
import re
# match alpha: 1 or 2 capital letters
pa = r'[A-Z]{1,2}'
# match number: 1-3 digits
pn = r'\d{1,3}'
# pattern: four match groups: alpha, number, alpha, number
p = '(%s)(%s)-(%s)(%s)' % (pa, pn, pa, pn)
_pat = re.compile(p)
def check_match(s):
m = _pat.search(s)
if not m:
return False
a0, n0, a1, n1 = m.groups()
if len(a0) != len(a1):
return False
if len(n0) > len(n1):
return False
return True
.join ('|') 나는 다음과 같이 추정한다 : P – Andrew
"이것들과 일치하는 것을 찾는다"고 말하기를 원한다면 여러 개의 정규 표현식을 항상 하나의 정규 표현식으로 바꿀 수있다. 당신의 직감이 여기에서 당신을 잘 돕고 있습니다. 증명 : 정규식을 정의하는 문자열을 '|' 당신은 그것을 구성했습니다. 즉,이 경우 Sean은 내가 방금 설명한 내용을 더 단순화 한 것을 제작했습니다. – Crisfole
실제로 귀하의 질문에 대답하지 않습니다 (저는 Sean이 이미 한 것으로 믿습니다). 나는 사용하는 속임수 시트를 추천하고 싶습니다. 나는 개인적으로 꽤 희귀 한 regexp를 사용한다. 그래서 나는 항상이 chetsheet와 상담한다 - http://www.addedbytes.com/cheat-sheets/regular-expressions-cheat-sheet/ - 나는 그것을 매우 유용하다고 느낀다. 그냥 책상 밖으로 어딘가에 그것을 밖으로 인쇄하십시오 :) – Timur