文字列の基本

================

文字列の結合はplus演算子にて可能

 >>> "a" + "b"
 'ab'

数値はstrを使う必要がある。

 >>> "a" + 1
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: cannot concatenate 'str' and 'int' objects
 >>> "a" + str(1)
 'a1'

逆に、文字列を数値として使いたかったらintを使う

 >>> 1 + "1"
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 TypeError: unsupported operand type(s) for +: 'int' and 'str'
 >>> 1 + int("1")
 2

文字列は「文字の配列」として扱える

 >>>
 # 0 = 1文字目
 >>> "abcdef"[0]
 'a'
 # 3文字目以降を表示
 >>> "abcdef"[3:]
 'def'
 # 3文字目までを表示
 >>> "abcdef"[:3]
 'abc'
 # -1文字目までを表示 = 最大より1文字少ない
 >>> "abcdef"[:-1]
 'abcde'
 # 2 から 4より前の文字を表示
 >>> "abcdef"[2:4]
 'cd'

簡単な文字列比較の例

 >>> "abc"[0] == "a"
 True
 >>> "ABC"[0] == "a"
 False

検索

 >>> "this is a pen".find("pen")
 10
 >>> "this is a pen".find("cup")
 -1
 # なので、含まれているかの比較は以下のようにする
 if string.find("cup") != -1:
   (-1 = 含まれていない「ではない」時の処理)

置き換え

 >>> "abc".replace("a", "b")
 'bbc'
 # 文字列も置き換えられる
 >>> "abc".replace("ab", "xx")
 'xxc'

高度な検索や置換の為に: 正規表現

正規表現は「パターン」を表します。 基本的な使い方を示します。

まずは、柔軟な検索の例として見ます。 ただし、検索だけでは正規表現の「おいしさ」は分かりませんので、 まずは例を実行した後、更に深く進めてください。

 # xyという文字列を探します
 >>> re.search("xy", "abcxyz")
 <_sre.SRE_Match object at 0x108714cc8>
 # aの後に「なにか2文字」あってxを探します
 >>> re.search("a..x", "abcxyz")
 <_sre.SRE_Match object at 0x108714d30>
 # aの後に「なにかが0文字以上」あってyzと続く文字列
 >>> re.search("a.*yz", "abcxyz")
 <_sre.SRE_Match object at 0x108714cc8>
 # aのあとに「bが1文字以上」あるもの
 >>> re.search("ab+", "aaaabbccc")
 <_sre.SRE_Match object at 0x108714d30>
 # なので、以下の例はひっかかりません
 >>> re.search("ab+", "aaaaccc")
 # でも、以下はaのあとにbが0文字以上なので引っかかります
 >>> re.search("ab*", "aaaaccc")
 <_sre.SRE_Match object at 0x108714d30>

なにがひっかかったのか?

groupという関数を利用します

 >>>
 # aのあとに任意の文字列があってyで終わるものを探す
 >>> re.search("a.*y", "abcxyz")
 <_sre.SRE_Match object at 0x108714d30>
 # なにが引っかかった?
 >>> re.search("a.*y", "abcxyz").group()
 'abcxy'

でも、結果がNoneの場合はgroupはないので気をつけてください。

 >>>
 # 以下の文字列は引っかからないので、groupという関数がない
 >>> re.search("a.*d", "abcxyz").group()
 Traceback (most recent call last):
   File "<stdin>", line 1, in <module>
 AttributeError: 'NoneType' object has no attribute 'group'

文字列の繰り返し

 >>>
 # 以下はabcを探します
 >>> re.search("abc", "abcabcabc").group()
 'abc'
 # 「abc」が*=0個以上続いている文字とマッチします
 >>> re.search("(abc)*", "abcabcabc").group()
 'abcabcabc'
 # *ではなく、{}で個数の指定も可能です
 >>> re.search("(abc){1,2}", "abcabcabc").group()
 'abcabc'
 # helのあとにloが1-2個続いているものとマッチします
 >>> re.search("hel(lo){1,2}", "hellolololo").group()
 'hellolo'

文字列単位でのOR

 >>>
 >>> re.search("(apple|orange)", "I have a pen.")
 >>> re.search("(pen|orange)", "I have a pen.").group()
 'pen'
 >>> re.search("(pen|orange)+", "I have a penpenpen.").group()
 'penpenpen'

賢い検索


大切なのは「パターン」という認識です。 例えば、incounter: 200という結果があったとします。 このとき、200だけを抜き出したいとします。

以下のように考えます。 “incounter”という文字列がある そのあとに”:”があって、” “がある。 そのあと、「数字が適当な数ある」

正規表現を学んだので、以上は”incounter: [0-9]+”や、 “incounter: \d+”と表せることが分かっています。 ここの[0-9]+や\d+の部分が欲しい訳です。

 >>> re.match("incounter: (\d+)", "incounter: 100").group(1)
 '100'

“\d+”の左右にある「()」がポイントです。これが「パターン」を意味します。 つまり、「数字が1個以上あるパターン」をmatch(するか確認)した訳です。 これを、groupで取り出します。 この中の(1)は「1個目のパターン」という意味です。

「1個目の」と言ったのは意味があります。例えば、 “incounter: 100, outcounter: 200”という文字列があります。

>>> re.match("incounter: (\d+), outcounter: (\d+)", "incounter: 100, outcounter: 200").group(1)
 '100'
 >>> re.match("incounter: (\d+), outcounter: (\d+)", "incounter: 100, outcounter: 200").group(2)
 '200'
 # groupsで全てをタプルの形で得ることもできます
 >>> re.match("incounter: (\d+), outcounter: (\d+)", "incounter: 100, outcounter: 200").groups()
 ('100', '200')

置換

subで「置き換え」ができます。 何に使うのかは分かりませんが、 “nで始まり:で終わる文字列”を空白に置き換えます。

 >>> re.sub("n.*:", "", "incount: 100")
 'i 100'

つぎは、「賢い置換」をします。 “\n”というnで、「n個目のパターン」という参照が可能です。

 >>> re.sub("incounter: (\d+)", "IN is \\1!", "incounter: 100")
 'IN is 100!'

このサンプル