Pythonで文字列の一部を削除(stripなど)

Modified: | Tags: Python, 文字列, 正規表現

Pythonで、文字列strの一部(部分文字列)を削除(除去)する方法について説明する。

拡張子の削除やディレクトリ部分の削除(ファイル名のみ抽出)など、パス文字列の処理については以下の記事を参照。

テキストファイルの中身の一部を削除したい場合は、ファイルを文字列として読み込んでから以降で説明する方法で処理して、再度保存すればよい。

任意の文字列を空文字列に置換して削除

文字列中の任意の文字列を削除したい場合、対象の文字列を空文字列''に置換する。

ここでは、replace()re.sub()の簡単な例のみを示す。置換についてのより詳しい内容は以下の記事を参照。複数の文字を置換するtranslate()などもある。

完全一致する文字列を削除: replace()

文字列strreplace()メソッドで、指定した文字列に完全一致する文字列を置換できる。空文字列''に置換すると削除される。

s = 'abc-xyz-123-789-ABC-XYZ'

print(s.replace('xyz', ''))
# abc--123-789-ABC-XYZ

正規表現にマッチする文字列を削除: re.sub()

正規表現にマッチする文字列を削除したい場合は正規表現モジュールresub()を使う。

ここで、\d+は1文字以上の数字の並びにマッチする正規表現パターン。123789が空文字列''に置換され、削除される。

import re

s = 'abc-xyz-123-789-ABC-XYZ'

print(re.sub('\d+', '', s))
# abc-xyz---ABC-XYZ

両端(先頭、末尾)の文字を削除: strip()

文字列の両端(先頭、末尾)の指定した文字を削除するにはstrip()を使う。

デフォルトでは両端の連続する空白文字が取り除かれる。改行\nや全角スペース\u3000やタブ\tなどが空白文字とみなされ削除される。

以下の例では、末尾の全角スペースやタブを分かりやすくするため組み込み関数repr()を使っている。

s = ' \n a b c \t'

print(s)
#  
#  a b c    

print(repr(s))
# ' \n a b c\u3000\t'

print(s.strip())
# a b c

print(repr(s.strip()))
# 'a b c'

文字列メソッドは新たなオブジェクトを返すので、元のオブジェクトはそのまま。元の変数に代入して上書きすることはできる。replace()や以降のlstrip()rstrip()でも同様。

s_strip = s.strip()
print(repr(s_strip))
# 'a b c'

print(repr(s))
# ' \n a b c\u3000\t'

s = s.strip()
print(repr(s))
# 'a b c'

引数に文字列を指定すると、その文字列に含まれる文字が両端から削除される。

指定した文字列に一致する文字列ではなく、指定した文字列に含まれる文字が削除される。例えば'abc'でも'cba'でも結果は同じ。間違えやすいので注意。一致した文字列を削除したい場合は、後述のremoveprefix(), removesuffix()を使う。

s = 'aabbcc-abc-aabbcc'

print(s.strip('abc'))
# -abc-

print(s.strip('cba'))
# -abc-

print(s.strip('ab'))
# cc-abc-aabbcc

引数に文字列を指定した場合は空白文字は削除されない。

s = ' \n aabbcc-abc-aabbcc \t'

print(repr(s))
# ' \n aabbcc-abc-aabbcc\u3000\t'

print(repr(s.strip('abc')))
# ' \n aabbcc-abc-aabbcc\u3000\t'

空白文字も取り除きたい場合は、明示的に指定するか、strip()を繰り返し適用する必要がある。

print(repr(s.strip('abc \n \t')))
# '-abc-'

print(repr(s.strip().strip('abc')))
# '-abc-'

先頭・末尾の文字数を指定して削除したい場合は後述のスライスを使う。

先頭(左側)の文字を削除: lstrip()

strip()は両端が対象だが、先頭のみを処理したい場合はlstrip()を使う。lは左側leftl

使い方はstrip()と同じ。

s = ' \n a b c  \t'

print(repr(s.lstrip()))
# 'a b c \u3000\t'

s = 'aabbcc-abc-aabbcc'

print(s.lstrip('abc'))
# -abc-aabbcc

末尾(右側)の文字を削除: rstrip()

末尾のみを処理したい場合はrstrip()を使う。rは右側rightr

使い方はstrip()と同じ。

s = ' \n a b c  \t'

print(repr(s.rstrip()))
# ' \n a b c'

s = 'aabbcc-abc-aabbcc'

print(s.rstrip('abc'))
# aabbcc-abc-

プレフィックスを削除: removeprefix()(Python3.9以降)

Python3.9から、プレフィックス(先頭の特定文字列)を削除するメソッドremoveprefix()が追加された。

引数に指定したプレフィックスから始まる場合、プレフィックスが削除された文字列が返される。一致しない場合は元の文字列がそのまま返される。

s = 'abc-abcxyz'

print(s.removeprefix('abc-'))
# abcxyz

print(s.removeprefix('aabc-'))
# abc-abcxyz

上述のlstrip()だと、引数に指定した文字列に含まれる文字がすべて削除されるので、プレフィックスのみを削除したいという用途には向かない。

print(s.lstrip('abc-'))
# xyz

サフィックスを削除: removesuffix()(Python3.9以降)

Python3.9から、サフィックス(末尾の特定文字列)を削除するメソッドremovesuffix()が追加された。

使い方はremoveprefix()と同じ。

s = 'abcxyz-xyz'

print(s.removesuffix('-xyz'))
# abcxyz

print(s.removesuffix('-xyzz'))
# abcxyz-xyz

プレフィックスとサフィックスを両方とも削除したい場合は、removeprefix()removesuffix()を続けて実行すればよい。

s = 'abc-abcxyz-xyz'

print(s.removeprefix('abc-').removesuffix('-xyz'))
# abcxyz

print(my_removeprefix(my_removesuffix(s, '-xyz'), 'abc-'))
# abcxyz

文字列の位置・文字数を指定して削除: スライス

スライスを使うと位置(0始まり)を指定して文字列の一部を取得できる。

負の値で後ろから位置を指定したり、省略して先頭から末尾まで指定したりすることもできる。

s = '0123456789'

print(s[3:7])
# 3456

print(s[3:-3])
# 3456

print(s[:5])
# 01234

print(s[5:])
# 56789

文字列の両端を削除したい場合は、上の例のように残す部分の位置をスライスで指定すればよい。例えば、6文字目以降を削除するという処理は、5文字目までを取得するという処理に等しい。

内側の文字列を削除したい場合は、両端から残す部分をスライスで取得して+演算子で連結する。

print(s[:3] + s[6:])
# 0126789

例えば、以下のように関数化できる。

start文字目からend文字目まで(endも含む)の文字列を削除する関数。

def remove_str_start_end(s, start, end):
    return s[:start] + s[end + 1:]

print(remove_str_start_end(s, 3, 5))
# 0126789

start文字目から文字数lengthの文字列を削除する関数。

def remove_str_start_length(s, start, length):
    return s[:start] + s[start + length:]

print(remove_str_start_length(s, 3, 5))
# 01289

文字列を要素とするリストの場合

リストに含まれる文字列を処理したい場合はリスト内包表記を利用して、要素ごとにstrip()などの文字列メソッドやスライスを適用する。

l = ['Alice', 'Bob', 'Charlie']

print([s.strip('bce') for s in l])
# ['Ali', 'Bo', 'Charli']

print([s[:2] for s in l])
# ['Al', 'Bo', 'Ch']

改行を含む文字列の場合

以下のような改行を含む文字列を例とする。

s = 'Alice\nBob\nCharlie'
print(s)
# Alice
# Bob
# Charlie

Pythonにおける改行についての詳細は以下の記事を参照。改行コード自体の削除や置換についても触れている。

各行の文字列の一部を削除

改行を含む文字列の各行の一部を削除する場合、replace()などの文字列全体に対して作用するメソッドは特に気にせず使える。

print(s.replace('li', ''))
# Ace
# Bob
# Chare

一方、strip()などの両端を処理するメソッドは、当然ながら、以下のように全体の先頭・末尾に対する処理となる。

print(s.strip('bce'))
# Alice
# Bob
# Charli

スライスも全体の位置に対して処理される。

print(s[2:-2])
# ice
# Bob
# Charl

各行をそれぞれ処理するには、まずsplitlines()で行ごとに分割する。

l_s = s.splitlines()
print(l_s)
# ['Alice', 'Bob', 'Charlie']

このリストに対してリスト内包表記を用いて、各行を処理する。

l_s_strip = [line.strip('bce') for line in l_s]
print(l_s_strip)
# ['Ali', 'Bo', 'Charli']

join()で一つの文字列に連結する。

s_line_strip = '\n'.join(l_s_strip)
print(s_line_strip)
# Ali
# Bo
# Charli

まとめて書くこともできる。以下は各行にスライスを使う例。

print('\n'.join([line[:2] for line in s.splitlines()]))
# Al
# Bo
# Ch

条件に応じて行を削除

条件を満たす、あるいは、条件を満たさない行を削除するには、リスト内包表記に条件を加える。

l_remove = [line for line in s.splitlines() if not line.startswith('B')]
print(l_remove)
# ['Alice', 'Charlie']

そのあと、join()で一つの文字列に連結する。

s_line_remove = '\n'.join(l_remove)
print(s_line_remove)
# Alice
# Charlie

まとめて書いてもよい。

print('\n'.join([line for line in s.splitlines() if 'li' in line]))
# Alice
# Charlie

上の例のように、startswith()endswith()で前方一致・後方一致を判定したり、in演算子で部分一致を判定したりできるほか、re.search()で正規表現パターンにマッチするかを判定することなどもできる。詳細は以下の記事を参照。

関連カテゴリー

関連記事