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ごとに違うので、それに影響されない方法が良いですよね。。