Python 100本ノックを始めました。 10本目

使用するファイルが文字化けしていたため、以下のサイトから最新の気温データをコピペして「hightemp.txt」を作成しました。
https://www.data.jma.go.jp/obd/stats/etrn/view/rankall.php

10. 行数のカウント

問題

  • 行数をカウントせよ.確認にはwcコマンドを用いよ

イメージした処理の流れ

linuxコマンドの「wc」を用いてカウントするのか、別の方法でカウントした結果を「wc」コマンドの結果と比較して確認するのか、よくわからなかったので両方作成しました!

linuxコマンドを使用しない行数カウント

①行数をカウントするファイル名を取得
②withを使用してファイルの読み込み
③ファイルに含まれる改行コードをカウント
④結果を出力

linuxコマンドを使用する行数カウント

⑤wcコマンドの実行
⑥wcコマンドの出力結果を加工
※-lオプションをつけても「行数 + ファイル名」で出力されるため
⑦結果を出力

作成したコード

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#行数をカウントせよ.確認にはwcコマンドを用いよ

import subprocess

#ファイル名を取得(①)
filename = input("行数をカウントするファイル名を指定してください:")

#linuxコマンドを使用しない行数カウント
with open(filename,"r") as f: #(②)
        #filename内の改行コードをカウント(③)
        num = f.read().count("\n")
        print("{} は {} 行記載されています。(python)".format(filename, num)) #(④)

#wcコマンドを使用した行数カウント
res = subprocess.run(['wc', '-l',filename,], encoding='utf-8', stdout=subprocess.PIPE) #(⑤)
#wcコマンドの結果をスペースで区切ってリストに追加(⑥)
line_num = res.stdout.split(" ")
#行数が表示される部分を抽出して表示(⑦)
print("{} は {} 行記載されています。(linuxコマンド)".format(filename, line_num[0]))

実行結果

行数をカウントするファイル名を指定してください:hightemp.txt
hightemp.txt は 21 行記載されています。(python)
hightemp.txt は 21 行記載されています。(linuxコマンド)

感想

この記事を書いていて、改行コードをカウントするだけでは「行数-1」になってしまうのではないか?という疑問がわきました。

上記の疑問を解決するために調べた結果、catに-eをつけると改行コードが見えることを知りました。
「LF」を「$」、「CR」を「M」で表示するらしいです。
cat -e hightemp.txtで確認したところ、以下のような結果が返ってきました。

# cat -e hightemp.txt
M-eM-^_M-<M-gM-^NM-^IM-gM-^\M-^L M-gM-^FM-^JM-hM-0M-7 * 41.1    2018-7-23$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-gM->M-^NM-fM-?M-^C   41.0    2018-8-8$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-iM-^GM-^QM-eM-1M-1   41.0    2018-8-6$
M-iM-+M-^XM-gM-^_M-%M-gM-^\M-^L M-fM-1M-^_M-eM-7M-^]M-eM-4M-^N  41.0    2013-8-12$
M-eM-2M-^PM-iM-^XM-^\M-gM-^\M-^L M-eM-$M-^ZM-fM-2M-;M-hM-&M-^K  40.9    2007-8-16$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-dM-8M--M-fM-^]M-!     40.8    2018-8-23$
M-fM-^]M-1M-dM-:M-,M-iM-^CM-= M-iM-^]M-^RM-fM-"M-^E     40.8    2018-7-23$
M-eM-1M-1M-eM-=M-"M-gM-^\M-^L M-eM-1M-1M-eM-=M-" *      40.8    1933-7-25$
M-eM-1M-1M-fM-"M-(M-gM-^\M-^L M-gM-^TM-2M-eM-:M-^\ *    40.7    2013-8-10$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-eM-/M-:M-fM-3M-^J     40.6    2019-8-15$
M-eM-^RM-^LM-fM--M-^LM-eM-1M-1M-gM-^\M-^L M-cM-^AM-^KM-cM-^AM-$M-cM-^BM-^IM-cM-^AM-^N   40.6    1994-8-8$
M-iM-^]M-^YM-eM-2M-!M-gM-^\M-^L M-eM-$M-)M-gM-+M-^\     40.6    1994-8-4$
M-eM-1M-1M-fM-"M-(M-gM-^\M-^L M-eM-^KM-^]M-fM-2M-<      40.5    2013-8-10$
M-eM-1M-1M-eM-=M-"M-gM-^\M-^L M-iM-<M- M-cM-^BM-1M-iM-^VM-"     40.4    2019-8-15$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-dM-8M-^IM-fM-^]M-!    40.4    2018-8-23$
M-eM-^_M-<M-gM-^NM-^IM-gM-^\M-^L M-hM-6M-^JM-hM-0M-7    40.4    2007-8-16$
M-fM-^VM-0M-fM-=M-^_M-gM-^\M-^L M-iM-+M-^XM-gM-^TM-0 *  40.3    2019-8-14$
M-fM-^DM-^[M-gM-^_M-%M-gM-^\M-^L M-eM-^PM-^MM-eM-^OM-$M-eM-1M-^K *      40.3    2018-8-3$
M-gM->M-$M-iM-&M-,M-gM-^\M-^L M-iM-$M-(M-fM-^^M-^W      40.3    2007-8-16$
M-gM->M-$M-iM-&M-,M-gM-^\M-^L M-dM-8M-^JM-iM-^GM-^LM-hM-&M-^K   40.3    1998-7-4$
M-fM-^DM-^[M-gM-^_M-%M-gM-^\M-^L M-fM-^DM-^[M-hM-%M-?   40.3    1994-8-5$

最終行まで、改行が入っていますね。
これであれば、カウント間違いはなさそうです。

ちなみに、-e無しは以下です。

# cat hightemp.txt
埼玉県 熊谷 *   41.1    2018-7-23
岐阜県 美濃     41.0    2018-8-8
岐阜県 金山     41.0    2018-8-6
高知県 江川崎   41.0    2013-8-12
岐阜県 多治見   40.9    2007-8-16
新潟県 中条     40.8    2018-8-23
東京都 青梅     40.8    2018-7-23
山形県 山形 *   40.8    1933-7-25
山梨県 甲府 *   40.7    2013-8-10
新潟県 寺泊     40.6    2019-8-15
和歌山県 かつらぎ       40.6    1994-8-8
静岡県 天竜     40.6    1994-8-4
山梨県 勝沼     40.5    2013-8-10
山形県 鼠ケ関   40.4    2019-8-15
新潟県 三条     40.4    2018-8-23
埼玉県 越谷     40.4    2007-8-16
新潟県 高田 *   40.3    2019-8-14
愛知県 名古屋 * 40.3    2018-8-3
群馬県 館林     40.3    2007-8-16
群馬県 上里見   40.3    1998-7-4
愛知県 愛西     40.3    1994-8-5

ただ、余りにも強引なやり方すぎたので、ほかのやり方を少し調べました。
そうすると、以下のような書き方を見つけ、こちらでカウントするほうがスマートで確実だなと思いまいした。

num_lines = sum(1 for line in open(filename))

改行コードはOSごとに違うので、それに影響されない方法が良いですよね。。