Pythonの文字列の比較方法|==, !=, in, re.match, re.search

Pythonの文字列同士を比較する方法には大きく分けて4つあります。

  • 完全一致:「==」「!=」演算子
  • 部分一致:「in」文
  • 前方一致(正規表現):re.match()
  • 完全一致(正規表現):re.search()

です。

文字列の比較は、例えば「文字列Aと文字列Bが一致したら処理Cを、一致しなかったら処理Dを行う」というような条件分岐(if文)プログラムを作るときによく使われます。

その時のためにそれぞれおさえておきましょう。

目次

1. Pythonの文字列の完全一致比較(==, !=)

文字列の比較は、比較演算子である「==」と「!=」を使うのがもっともオーソドックスな方法です。

1.1. ==演算子で完全一致かどうかを比較

「==」は、比較した文字列同士が、完全に一致する場合に True を、完全一致でない場合に False を返します。

なお演算子については、「Pythonの演算子の一覧と解説」をご確認ください。

まず比較のために以下の3つの文字列を作成します。

In [1]:
text_a = "this is a pen."
text_b = "this is a pen."
text_c = "this is a pencil."

text_a と text_b を比較してみましょう。

In [2]:
text_a == text_b
Out[2]:
True

2つの文字列は完全に一致しているため True が返されます。続いて text_a と text_c を比較してみましょう。

In [3]:
text_a == text_c
Out[3]:
False

2つの文字列は完全一致ではないため False と返されます。

1.2.  !=演算子で完全一致でないかどうかを比較

比較演算子「!=」は「==」と真逆で、比較した文字列同士が、完全一致でない場合に True を、完全一致の場合に False を返します。

早速見ていきましょう。先ほどと同じ3つの文字列を作ります。

In [1]:
text_a = "this is a pen."
text_b = "this is a pen."
text_c = "this is a pencil."

text_a と text_b を比較してみましょう。

In [2]:
text_a != text_b
Out[2]:
False

2つの文字列は完全一致なので False と返されます。続いて、text_a とtext_c の比較です。

In [3]:
text_a != text_c
Out[3]:
True

2つの文字列は、完全一致ではないので True と返されます。

注. 比較演算子の 「==」と「is」の違い

比較演算子の「==」と「is」、「!=」と「is not」はよく混同されます。これらは全く別物です。「is」や「is not」は、同一オブジェクト(インスタンス)かどうかを比較する演算子です。そのため、「is」を使うと、文字列が同じでも False と返される場合があります。

そのため文字列の比較は、必ず「==」や「!=」で行うよう癖づけておきましょう。

厳密には、文字列には「イミュータブル(変更不可能)」という特性があるので、特に不都合はありません。しかし「ミュータブル(変更可能)」なオブジェクトであるリストなどを比較する際に、「==」や「!=」を使うよう癖づけられていないと問題が起きる場合があります。

詳しくは、「Pythonのリストを比較する方法」で解説していますので確認しておきましょう。

なお文字列のイミュータビリティという特徴については「初心者のためのPythonの文字列操作の基本」で詳しく解説しています。

1.3. 「==」演算子を使ったプログラム例

「==」演算子による文字列比較と条件分岐のif文を組み合わせると次のようなコードを書くことができます。住んでいる地域を入力したら、その天気を返してくれるプログラムです。

In [1]:
''' 天気予報プログラム'''

address = input('お住いの地域を入力してください。')

if address == '関東':
    print('今日の天気は晴れです。')
elif address == '関西':
    print('今日の天気は曇りです。')
else:
    print('今日の天気は雨です。')
お住いの地域を入力してください。関東
今日の天気は晴れです。

このように文字列比較と条件分岐(if文)を併用したプログラムはよく見られます。

2. Pythonの文字列の部分一致比較(in文)

in ステートメントを使った比較も、よく使うものの一つでしょう。これを使うと、ある文字列が、任意の文字列を含むかどうか(部分一致かどうか)を確認することができます。

次の例をご覧ください。

In [1]:
url = "http://www.google.com/gmail"
googleDomain ="google.com"
googleDomain in url
Out[1]:
True

「url」には、Gメールのアドレスを示す文字列を代入しています。「googleDomain」には、グーグルのドメインを代入しています。そして、「googleDomain in url」で、「url」の中に「googleDomain」が含まれているかを確認しています。

含まれていますので、答えは True ですね。

1.1. 「==」演算子と「in」文による文字列比較の違い

以下のコードを見てみましょう。

In [2]:
text = 'this is a pencil.'
'this is a pen' in text
Out[1]:
True

==演算子では、’this is a pencil’ と ‘this is a pen’の比較ではFalseと出ていましたが、in文ではTrueになります。これはin文は部分一致するかどうかを返すからです。

この点が異なりますので使い分けましょう。

1.2. in文による文字列比較を使ったプログラム例

さて、ここでも「in」文を使った非常に簡単な条件分岐プログラム例を見てみましょう。入力したメールアドレスが、GメールかYahoo!メールかそれ以外かを判別するものです。

In [1]:
'''メールアドレス判定プログラム'''

mail = input('メールアドレスを入力してください。')

if 'gmail.com' in mail:
    print('これはGメールです。')
elif 'yahoo.co.jp' in mail:
    print('これはYahoo!メールです。')
else:
    print('これはGメールでもYahoo!メールでもありません。')
メールアドレス判定プログラム
メールアドレスを入力してください。example@gmail.com
これはGメールです。

4. 正規表現による文字列比較(re.match, re.search)

ここからは中級編です。もっと複雑な比較を行いたい場合は、正規表現を使う方法があります。

そしてPythonでは正規表現による比較はreモジュールのre.match()を使います。

モジュールについては『Pythonのモジュールについて抑えておくべき知識とよく使うもの一覧』でご確認ください。

正規表現は中級編なので、プログラミング初学者は、まだ覚える必要はありません。将来、正規表現を使う必要性が出てきた時のために流し読むぐらいで十分だとお考えください。

3.1. re.match|文字列の先頭に条件と一致する文字列があるかを比較

match関数を使うと、ある文字列の先頭に、任意の条件と一致する文字列があるかどうかを確認することができます。

match関数の基本構文

match関数の基本構文は次の通りです。

import re #reモジュールのインポート
re.match("正規表現パターン(比較したい文字列)", 比較対象の文字列)

まず、match 関数は re モジュールの関数なので、最初に “import re” でモジュールを読み込んでおく必要があります。そして、第一引数に、比較したい文字列を正規表現パターンで入力します。

例えば、小文字のアルファベットでできている文字列をを確認したい場合は[a-z]+と書きます。4桁の数値でできている文字列を確認したい場合は[0-9]{4}と書きます。正規表現のパターンは「正規表現一覧」で、ほぼ一通り確認することができます。

match関数の使用例

それでは、例をみていきましょう。

以下の電話番号をもつ変数を作りました。

In [1]:
tel = "03-1111-2222"

以下のように書くと、この文字列(数値)の最初に、「3桁の数値-4桁の数値-4桁の数値」という構成と一致する文字列があるかどうかを確認することができます。

In [2]:
import re
re.match("[0-9]{2}-[0-9]{4}-[0-9]{4}", tel)
Out[2]:
<_sre.SRE_Match object; span=(0, 12), match='03-1111-2222'>

「[0-9]{2}-[0-9]{4}-[0-9]{4}」とありますが、例えば、「[0-9]{2}」は0から9の間のいずれかの数値を含む2桁の数字ということを表す正規表現です。それらをハイフン(-)で繋いでいます。つまり、「2桁-4桁-4桁」という構成の数値を示しています。

実行結果を見てみると、 <_sre.SRE_Match object; span=(0, 12), match=’03-1111-2222’> となっていますね。この特殊な返り値は「マッチオブジェクト型」といいます。

「span=(0, 12)は、インデックス番号0番から12番に渡って、「3桁の数値-4桁の数値-4桁の数値」という構成と一致する文字列があることを示しています。「match=’03-1111-2222’」は、「該当する文字列は、03-1111-2222です。」ということを返しています。

マッチオブジェクトでは様々なメソッドが用意されています。以下はその一例です。

In [3]:
''' groupメソッド '''
print(match_obj.group())  #  条件に一致する文字列を抽出
''' spanメソッド '''
print(match_obj.span())    #  条件に一致する文字列の位置を特定
''' startメソッド '''
print(match_obj.start())   #  条件に一致する文字列の開始位置を特定 
''' endメソッド '''
print(match_obj.end())     #  条件に一致する文字列の終了位置を特定
03-1111-2222
(0, 12)
0
12

マッチオブジェクトのメソッドについては、以下のページで確認することができます。

なお、match関数は先頭の文字列だけを参照します。そのため、比較したい文字列が先頭にない場合には何も返ってきません。

次の例では、文字列の中に「2桁-4桁-4桁」の構成の文字列が含まれています。

In [1]:
tel_2 = "my phone number is 03-1111-2222"

しかし、match関数を実行しても何も返ってきません。

In [2]:
import re
re.match("[0-9]{2}-[0-9]{4}-[0-9]{4}", tel_2)
Out[None]:
 

このようにmatch関数は、先頭の文字だけを参照します。 変数”tel2″の最初の文字列はアルファベットなので、以下のような比較を行うことは可能です。

In [3]:
import re
re.match(r"[a-z]{2}", tel_2)
Out[3]:
<_sre.SRE_Match object; span=(0, 1), match='my'>

この例では、最初に「r”[a-z]{2}”」と入力しています。これは小文字アルファベットからなる2文字があるかどうかを比較するという正規表現です。

ちなみに、細かいですが、文字列の最初につけている r は、Python の raw string 記法というもので、文字列の正規表現を入力する際には癖づけておきたいものです。r をつけた場合とつけない場合にどうなるかは「【Python 3系】re.subでの置換方法」で検証されていますので、確認しておいて下さい。

返り値を見てみると、「span=(0, 1)」「match = ‘my’」と表示されていますね。これは、インデックス番号の0番と1番に、比較対象と合致する文字列があり、その文字列は「my」ですよと返してくれているのです。

3.2. re.search|文字列全体から条件に一致する文字列があるかを検索

なお、文字列の先頭ではなく文字列全体から条件に一致する文字列があるかどうかを知りたい時はre.search関数を使います。

In [1]:
tel_2 = "my phone number is 03-1111-2222"
import re
re.search("[0-9]{2}-[0-9]{4}-[0-9]{4}", tel_2)
Out[2]:
<re.Match object; span=(19, 31), match='03-1111-2222'>

文字列の先頭にあるかどうかは関係なく、文字列全体の中から条件に一致したものがあるかどうかを検索してくれていますね。返り値も、re.match()と同じくマッチオブジェクト型です。

これに関しては『Pythonの文字列の検索方法|find, in, count, re.search』でも解説していますので、併せてご確認ください。

re.match()とre.searchの違い

re.match()は文字列の先頭でのみ一致するかどうかを確認し、re.search()は文字列の位置に関わらず一致するかどうかを確認する関数です。

In [1]:
import re
print(re.match('c', 'abcdef'))
print(re.search('c', 'abcdef'))
None
<re.Match object; span=(2, 3), match='c'>

ただしre.search()でも、先頭文字を意味する’^’をつけると文字列の先頭でのみ一致があるかどうかに制限することができます。

In [2]:
print(re.match('c', 'abcdef'))
print(re.search('^c', 'abcdef'))
print(re.search('^a', 'abcdef'))
None
None
<re.Match object; span=(0, 1), match='a'>

一番の違いは、第三引数で’re.MULTILINE’と渡した時に見られます。これを書くと、re.search()では各行の先頭文字が一致するかどうかを確認します。

re.matchでは行に関わらず、文字列全体の先頭文字のみを確認します。

In [3]:
str = 'A\nB\nC'

print(re.match('C', str, re.MULTILINE))
print(re.search('^C', str, re.MULTILINE))
None
<re.Match object; span=(4, 5), match='C'>

これも、しっかり把握しておくとよいでしょう。

3.3. 正規表現による文字列比較を使ったプログラム例

さて、正規表現の文字列比較ができると、「==」演算子や「in文」よりも、さらに複雑な条件による分岐を作ることができるようになります。

例えば、次のコードは携帯電話番号が「3桁-4桁-4桁」で入力されているかどうかを判別するものです。最初の3桁は、070か080か090でなければNGです。

In [1]:
phone = input("携帯電話番号を'-'込みで入力してください:")

if re.match('^(070|080|090)-[\d]{4}-[\d]{4}$', phone):
    print('ありがとうございます。')
else:
    print('それは携帯電話ではありません。')
携帯電話番号を'-'込みで入力してください:03-1111-2222
それは携帯電話ではありません。

正規表現は、使いこなせるとほとんど無限の条件を設定することができます。

4. まとめ

最後に、文字列の比較についてまとめておきます。簡単ですが、以下の3つのように使い分けると良いでしょう。

  • 完全一致の比較には「==」「!=」演算子を使う(「is」「isnot」は使わない)。
  • 部分一致の比較には「in」演算子を使う。
  • 【正規表現】前方一致の比較にはre.match()を使う。
  • 【正規表現】位置を問わない比較にはre.search()を使う。

正規表現は、プログラミング初学者にはややこしく感じられるかもしれませんが、一度本腰を入れて理解してしまえば、そんなことはないことが分かると思います。

粘り強く学習していきましょう。



よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

コメント

コメントする

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください

目次
閉じる