1. ホーム
  2. python

Pythonで、文字列が特定の文字だけを含んでいるかどうかを確認する方法は?

2023-10-18 17:26:18

質問

Pythonで、文字列が特定の文字だけを含むかどうかを確認する方法は?

私はa..z、0..9、および.(ピリオド)だけを含み、他の文字を含まない文字列をチェックする必要があります。

私は各文字を繰り返し、文字がa..z、0..9、または.であることをチェックできましたが、それは遅いでしょう。

正規表現でどうやるか、今ひとつはっきりしない。

これは正しいのでしょうか?もっと簡単な正規表現か、もっと効率的な方法を提案していただけないでしょうか。

#Valid chars . a-z 0-9 
def check(test_str):
    import re
    #http://docs.python.org/library/re.html
    #re.search returns None if no position in the string matches the pattern
    #pattern to search for any character other then . a-z 0-9
    pattern = r'[^\.a-z0-9]'
    if re.search(pattern, test_str):
        #Character other then . a-z 0-9 was found
        print 'Invalid : %r' % (test_str,)
    else:
        #No character other then . a-z 0-9 was found
        print 'Valid   : %r' % (test_str,)

check(test_str='abcde.1')
check(test_str='abcde.1#')
check(test_str='ABCDE.12')
check(test_str='_-/>"!@#12345abcde<')

'''
Output:
>>> 
Valid   : "abcde.1"
Invalid : "abcde.1#"
Invalid : "ABCDE.12"
Invalid : "_-/>"!@#12345abcde<"
'''

どのように解決するのですか?

最終的な(?)編集

答え、関数でラップされ、注釈付きの対話式セッション。

>>> import re
>>> def special_match(strg, search=re.compile(r'[^a-z0-9.]').search):
...     return not bool(search(strg))
...
>>> special_match("")
True
>>> special_match("az09.")
True
>>> special_match("az09.\n")
False
# The above test case is to catch out any attempt to use re.match()
# with a `$` instead of `\Z` -- see point (6) below.
>>> special_match("az09.#")
False
>>> special_match("az09.X")
False
>>>

注:この答えのさらに下にre.match()を使用することとの比較はあります。最終的な答えがTrueであるとき、match()はsearch()よりはるかに大きなオーバーヘッドを持っているようです。これは不可解で、(おそらくそれはNoneの代わりにMatchObjectを返すコストです)さらに調査することを保証するかもしれません。

==== Earlier text ====

以前] 受け入れられた回答は、いくつかの改良が必要です。

(1) プレゼンテーションは、対話的なPythonセッションの結果であるかのように見えます。

reg=re.compile('^[a-z0-9\.]+$')
>>>reg.match('jsdlfjdsf12324..3432jsdflsdf')
True

を返しますが、match()は True

(2) match()と一緒に使う場合は ^ は冗長であり、同じパターンで ^

(3) どんな再パターンでも自動的に何も考えずに生文字列を使用することを促進すべきである。

(4) ドット/ピリオドの前にあるバックスラッシュは冗長です。

(5) OPのコードより遅い!

prompt>rem OP's version -- NOTE: OP used raw string!

prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[^a-z0-9\.]')" "not bool(reg.search(t))"
1000000 loops, best of 3: 1.43 usec per loop

prompt>rem OP's version w/o backslash

prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[^a-z0-9.]')" "not bool(reg.search(t))"
1000000 loops, best of 3: 1.44 usec per loop

prompt>rem cleaned-up version of accepted answer

prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile(r'[a-z0-9.]+\Z')" "bool(reg.match(t))"
100000 loops, best of 3: 2.07 usec per loop

prompt>rem accepted answer

prompt>\python26\python -mtimeit -s"t='jsdlfjdsf12324..3432jsdflsdf';import
re;reg=re.compile('^[a-z0-9\.]+$')" "bool(reg.match(t))"
100000 loops, best of 3: 2.08 usec per loop

(6) 間違った答えを出す可能性があります!

>>> import re
>>> bool(re.compile('^[a-z0-9\.]+$').match('1234\n'))
True # uh-oh
>>> bool(re.compile('^[a-z0-9\.]+\Z').match('1234\n'))
False