受け取ったテキストファイルにLF、CR、CRLFが混在していて、
CRLFとCRを置換する必要に迫られたとき。
以外とググっても出てこなかったので備忘録として残します。
Python3.7
事例
2行目の末尾にCRLFが存在(^MがCR)。
これを別の文字に置換したい。
$ cat crlf.txt
1 2 3
4 5 6^M
7 8 9
(×) テキストファイル扱いで開く
Pythonで通常のテキストファイル扱いでOpenすると、
あれ…?置き換えされない?
with open('crlf.test') as f:
for line in f:
line = line.replace('\r\n','XXX') #CRLFを置換
print(line)
# 1 2 3
#
# 4 5 6
#
# 7 8 9
どうやら、Pythonが親切にもCRを外してくれるようです。
CentOS上で動作させたGoやC#も同様だったので、OS環境に依存している模様。
(〇)バイナリファイル扱いで開く
バイナリモードで開けば、勝手に変換されることはないのでは?と思い、やってみた。
読み取ったデータはバイト列なので、デコードして文字列に変換する のステップが必要。
バイナリだから文字列変換後じゃないと改行を判別できないのでは…
と思いきや、バイナリのLFを改行として認識したうえで1行を返してくれるので楽ちん。
with open('crlf.test','rb') as f:
for line in f:
line = line.decode().replace('\r\n','XXX')
print(line)
# 1 2 3
#
# 4 5 6XXX
# 7 8 9
CRLF が XXX になったので、改行も1つ無くなっている。
CRだけ置換するとどうなるか。
with open('crlf.test','rb') as f:
for line in f:
line = line.decode().replace('\r','XXX')
print(line)
# 1 2 3
#
# 4 5 6XXX
#
# 7 8 9
ちゃんとCRだけ置換され、CRLFのLF部分は残っている。
結論
改行コードが混在するテキストファイルを扱うときは、
バイナリモードでテキストファイルを開きましょう