note.nkmk.me

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

Date: 2020-04-01 / tags: Python, 文字列処理, 正規表現

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

  • 任意の文字列を空文字列に置換して削除
    • 完全一致する文字列を削除: replace()
    • 正規表現にマッチする文字列を削除: re.sub()
  • 両端(先頭、末尾)の文字を削除: strip()
  • 先頭(左側)の文字を削除: lstrip()
  • 末尾(右側)の文字を削除: rstrip()
  • 文字列の位置・文字数を指定して削除: スライス
  • 文字列を要素とするリストの場合
  • 改行を含む文字列の場合
    • 各行の文字列の一部を削除
    • 条件に応じて行を削除

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

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

スポンサーリンク

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

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

ここでは、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も空白文字とみなされ削除される。print()の出力だと分かりにくいが、元の文字列にはcのあとに全角スペースがある。

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'

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

文字列メソッドは新たなオブジェクトを返すので、元のオブジェクトはそのまま。元の変数に代入して上書きすることはできる。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'でも結果は同じ。間違えやすいので注意。

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-

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

スライスを使うと位置(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()で正規表現パターンにマッチするかを判定することなどもできる。詳細は以下の記事を参照。

スポンサーリンク
シェア
このエントリーをはてなブックマークに追加

関連カテゴリー

関連記事