ProgramingTip

어디에서 문자, 숫자, 밑줄 및 대시 만 포함되어 있는지 확인하십시오.

bestdevel 2020. 10. 7. 07:56
반응형

어디에서 문자, 숫자, 밑줄 및 대시 만 포함되어 있는지 확인하십시오.


보다 우아한 방법을 찾고 있습니다.


정규식은 아주 약간 코드로 트릭을 수행합니다.

import re

...

if re.match("^[A-Za-z0-9_-]*$", my_little_string):
    # do something here

[편집] 아직 언급되지 않은 또 다른 솔루션이 대부분의 경우 지금까지 언급 된 솔루션을 능가하는 것입니다.

string.translate를 사용하여 유효한 모든 유효한 문자를 교체하고 유효하지 않은 문자가 있는지 확인하십시오. 이 작업을 수행하기 위해 기본 C 함수를 사용하기 때문에 매우 빠르며 Python 바이트 코드가 거의 포함되지 않습니다.

분명히 성능이 전부는 아닙니다. 성능이 중요한 코드 경로에 있지 않을 때 가장 가독성이 좋은 솔루션을 찾는 것이 아마도 최상의 접근 방식 일 것입니다.하지만 솔루션이 어떻게 쌓이는 지보기 위해 지금까지 제안 된 모든 방법에 대한 성능 비교가 있습니다. check_trans는 string.translate 메소드를 사용하는 것입니다.

테스트 코드 :

import string, re, timeit

pat = re.compile('[\w-]*$')
pat_inv = re.compile ('[^\w-]')
allowed_chars=string.ascii_letters + string.digits + '_-'
allowed_set = set(allowed_chars)
trans_table = string.maketrans('','')

def check_set_diff(s):
    return not set(s) - allowed_set

def check_set_all(s):
    return all(x in allowed_set for x in s)

def check_set_subset(s):
    return set(s).issubset(allowed_set)

def check_re_match(s):
    return pat.match(s)

def check_re_inverse(s): # Search for non-matching character.
    return not pat_inv.search(s)

def check_trans(s):
    return not s.translate(trans_table,allowed_chars)

test_long_almost_valid='a_very_long_string_that_is_mostly_valid_except_for_last_char'*99 + '!'
test_long_valid='a_very_long_string_that_is_completely_valid_' * 99
test_short_valid='short_valid_string'
test_short_invalid='/$%$%&'
test_long_invalid='/$%$%&' * 99
test_empty=''

def main():
    funcs = sorted(f for f in globals() if f.startswith('check_'))
    tests = sorted(f for f in globals() if f.startswith('test_'))
    for test in tests:
        print "Test %-15s (length = %d):" % (test, len(globals()[test]))
        for func in funcs:
            print "  %-20s : %.3f" % (func, 
                   timeit.Timer('%s(%s)' % (func, test), 'from __main__ import pat,allowed_set,%s' % ','.join(funcs+tests)).timeit(10000))
        print

if __name__=='__main__': main()

내 시스템의 결과는 다음과 가변적입니다.

Test test_empty      (length = 0):
  check_re_inverse     : 0.042
  check_re_match       : 0.030
  check_set_all        : 0.027
  check_set_diff       : 0.029
  check_set_subset     : 0.029
  check_trans          : 0.014

Test test_long_almost_valid (length = 5941):
  check_re_inverse     : 2.690
  check_re_match       : 3.037
  check_set_all        : 18.860
  check_set_diff       : 2.905
  check_set_subset     : 2.903
  check_trans          : 0.182

Test test_long_invalid (length = 594):
  check_re_inverse     : 0.017
  check_re_match       : 0.015
  check_set_all        : 0.044
  check_set_diff       : 0.311
  check_set_subset     : 0.308
  check_trans          : 0.034

Test test_long_valid (length = 4356):
  check_re_inverse     : 1.890
  check_re_match       : 1.010
  check_set_all        : 14.411
  check_set_diff       : 2.101
  check_set_subset     : 2.333
  check_trans          : 0.140

Test test_short_invalid (length = 6):
  check_re_inverse     : 0.017
  check_re_match       : 0.019
  check_set_all        : 0.044
  check_set_diff       : 0.032
  check_set_subset     : 0.037
  check_trans          : 0.015

Test test_short_valid (length = 18):
  check_re_inverse     : 0.125
  check_re_match       : 0.066
  check_set_all        : 0.104
  check_set_diff       : 0.051
  check_set_subset     : 0.046
  check_trans          : 0.017

번역 접근 방식은 대부분의 경우 가장 좋은 것입니다. 긴 유효한 유효한 사용하면 극적으로 길지만 test_long_invalid의 정규식에 의해 패배합니다 (아마도 정규식이 즉시 구제 될 수 있습니다 번역은 항상 전체를 스캔해야합니다). 접근 방식은 일반적으로 최악의 경우 빈 경우에만 정규식을 사용합니다.

all (x in s에 대해 allowed_set에서 x)을 사용하면 조기에 구제되면 잘 수행되지만 모든 문자를 반복해야한다면 좋지 않을 수 있습니다. isSubSet 및 집합 차이는 비교할 수 있으며 데이터에 관계없이 문자열 길이에 일관되게 비례합니다.

모든 유효한 문자와 일치하는 정규식 메소드와 유효하지 않은 문자를 검색하는 것 사이에는 비슷한 차이가 있습니다. 일치는 길지만 완전히 유효한 문자열을 검사 할 때 약간 더 잘 수행되지만 문자열 끝 부분에있는 유효하지 않은 문자의 경우 더 나쁩니다.


이 목표를 달성하는 방법에는 여러 가지가 있으며 일부는 다른 것보다 명확합니다. 각 예제에서 'True'는 전달 된 문자열이 유효 함을 의미하고 'False'는 잘못된 문자가 포함되어 있음을 의미합니다.

우선, 순진한 접근 방식이 있습니다.

import string
allowed = string.letters + string.digits + '_' + '-'

def check_naive(mystring):
    return all(c in allowed for c in mystring)

그런 다음 정규 표현식을 사용하면 re.match ()로이를 수행 할 수 있습니다. '-'는 [] 끝에 있어야합니다. 그렇지 않으면 '범위'구분 기호로 사용됩니다. 또한 '문자열의 끝'을 의미하는 $에 유의하십시오. 이 질문에 언급 된 다른 답변은 특수 문자 클래스 '\ w'를 사용합니다. 빠른 참조 가이드를 찾아 볼 필요없이 이해하기 쉽고 특수 문자 클래스가 더 쉽기 때문에 항상 []를 사용하여 명시적인 문자 클래스 범위를 사용하는 것을 선호합니다. 케이스.

import re
CHECK_RE = re.compile('[a-zA-Z0-9_-]+$')
def check_re(mystring):
    return CHECK_RE.match(mystring)

또 다른 솔루션은 정규식과 역 일치를 수행 할 수 있다는 점을 지적했습니다. 지금 여기에 포함 시켰습니다. ^가 사용되기 때문에 [^ ...]은 문자 클래스를 반전시킵니다.

CHECK_INV_RE = re.compile('[^a-zA-Z0-9_-]')
def check_inv_re(mystring):
   return not CHECK_INV_RE.search(mystring)

'set'개체로 까다로운 작업을 수행 할 수도 있습니다. 허용되는 모든 문자를 원래 문자열에서 제거하고 a) 아무것도 포함하지 않거나 b) 문자열에서 문제가되는 문자를 포함하는 집합을 남겨 두는이 예제를 살펴보십시오.

def check_set(mystring):
    return not set(mystring) - set(allowed)

대시와 밑줄이 아니라면 가장 쉬운 해결책은

my_little_string.isalnum()

( Python 라이브러리 참조의 섹션 3.6.1 )


정규식을 사용하는 대신 세트에서 수행 할 수 있습니다.

from sets import Set

allowed_chars = Set('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-')

if Set(my_little_sting).issubset(allowed_chars):
    # your action
    print True

 pat = re.compile ('[^\w-]')

 def onlyallowed(s):
    return not pat.search (s)

정규 표현식은 매우 유연 할 수 있습니다.

import re;
re.fullmatch("^[\w-]+$", target_string) # fullmatch looks also workable for python 3.4

\w: 뿐 [a-zA-Z0-9_]

따라서 -하이픈 문자를 정당화 하려면 문자 를 추가해야합니다 .

+: 선행 문자의 하나 이상의 반복과 일치합니다. 빈 입력을 받아들이지 않는 것 같습니다. 그러나 그렇게 할 경우 *.

^: 문자열의 시작과 일치합니다.

$: 문자열의 끝과 일치합니다.

다음 대소 문자를 피해야하므로이 두 특수 문자가 필요합니다. &여기 와 같이 원하지 않는 문자 가 일치하는 패턴 사이에 나타날 수 있습니다.

&&&PATTERN&&PATTERN


그럼 정규식의 도움을 요청할 수 있습니다.

암호:

import re

string = 'adsfg34wrtwe4r2_()' #your string that needs to be matched.
regex = r'^[\w\d_()]*$' # you can also add a space in regex if u want to allow it in the string  
if re.match(regex,string):
    print 'yes'
else: 
    print 'false'

산출:

yes  

도움이 되었기를 바랍니다 :)


항상 목록 이해력을 사용하고 결과를 모두 확인할 수 있습니다. 정규식을 사용하는 것보다 리소스 집약적입니다. all([c in string.letters + string.digits + ["_", "-"] for c in mystring])


다음은 Jerub의 "순진한 접근 방식"에 기반한 것입니다 (내가 아니라 그의 말이 순진합니다!).

import string
ALLOWED = frozenset(string.ascii_letters + string.digits + '_' + '-')

def check(mystring):
    return all(c in ALLOWED for c in mystring)

경우 ALLOWED문자열 한 후 생각 c in ALLOWED이 일치하는 항목을 찾을 수 없거나 끝에 도달 할 때까지 문자열의 각 문자를 통해 반복하는을 포함한다. Joel Spolsky의 말을 인용하자면 Shlemiel the Painter 알고리즘 입니다.

그러나 세트에 존재하는지 테스트하는 것이 더 효율적이거나 적어도 허용되는 문자 수에 따라 덜 의존해야합니다. 확실히이 접근 방식은 내 컴퓨터에서 조금 더 빠릅니다. 명확하고 대부분의 경우에 충분히 잘 수행된다고 생각합니다 (저의 느린 컴퓨터에서는 몇 분의 1 초에 수만 개의 짧은 문자열을 확인할 수 있습니다). 나는 그것을 좋아한다.

실제로 내 컴퓨터에서 정규 표현식은 몇 배 더 빠르게 작동하며 이것만큼 간단합니다 (아마도 더 간단합니다). 이것이 아마도 최선의 방법 일 것입니다.


정규식을 사용하고 일치하는지 확인하십시오!

([a-z][A-Z][0-9]\_\-)*

참고 URL : https://stackoverflow.com/questions/89909/how-do-i-verify-that-a-string-only-contains-letters-numbers-underscores-and-da

반응형