#これまでの経緯などについて
最初の投稿を参照ください
#ノック状況
9/24追加
#第2章: UNIXコマンドの基礎
hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.
#015. 末尾のN行を出力
自然数Nをコマンドライン引数などの手段で受け取り、入力のうち末尾のN行だけを表示せよ.確認にはtailコマンドを用いよ.
#-*- coding:utf-8 -*-
import codecs
import subprocess
def tail(data,N):
max = len(data)
print(''.join(data[max-N:]))
if __name__=="__main__":
filename = 'hightemp.txt'
basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
f = codecs.open(filename,'r','utf-8')
N=3
tail(f.readlines(),N)
#tailコマンドで確認
output=subprocess.check_output(["tail","-n",str(N),basepath+filename])
print(output.decode('utf-8'))
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
山梨県 大月 39.9 1990-07-19
山形県 鶴岡 39.9 1978-08-03
愛知県 名古屋 39.9 1942-08-02
感想:工夫ポイントはjoinを始める行の指定の仕方かな
#016. ファイルをN分割する
自然数Nをコマンドライン引数などの手段で受け取り,入力のファイルを行単位でN分割せよ.同様の処理をsplitコマンドで実現せよ
-*- coding:utf-8 -*-
import codecs
import subprocess
import math
def split(data,N):
index=0
#書き出すファイル数を計算する
page=math.ceil(len(data)/N)
for i in range(0,page):
#リストを文字列にして書き出すデータをwrite_dataに追記
write_data=''.join(data[index:N+index])
index+=N
f=codecs.open('write_data'+str(index),'w','utf-8')
f.write(write_data)
if __name__ == "__main__":
filename = 'hightemp.txt'
basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
N = 15
f=codecs.open(filename,'r','utf-8')
split(f.readlines(),N)
output=subprocess.check_output(["split","-l",str(N),basepath+filename])
split関数によりwrite_data15とwrite_data30のファイルが出力された
write_data15
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
(結果が長いので略)
write_data30
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
(結果が長いので略)
splitコマンドによりxaaとxabのファイルが出力された
xaa
高知県 江川崎 41 2013-08-12
埼玉県 熊谷 40.9 2007-08-16
岐阜県 多治見 40.9 2007-08-16
(結果が長いので略)
xab
山形県 酒田 40.1 1978-08-03
岐阜県 美濃 40 2007-08-16
群馬県 前橋 40 2001-07-24
(結果が長いので略)
Process finished with exit code 0
感想:split関数を作成するときに悩んだのはN数行で1ファイルを作成するときのページ数の計算の仕方とファイル名の命名の仕方。。。
#017. 1列目の文字列の異なり
1列目の文字列の種類(異なる文字列の集合)を求めよ.確認にはsort, uniqコマンドを用いよ.
# -*- coding:utf-8 -*-
import codecs
import subprocess
def sort_uniq(data):
cut_temp = []
sort_temp = []
uniq_temp = []
#cut -f 1の働き
for temp in data:
cut_temp.append(temp.split()[:1])
#sortの働き
sort_temp = sorted(cut_temp)
#uniqの働き
for temp in sort_temp:
if temp not in uniq_temp:
uniq_temp.append(temp)
#listをstrに変換後、余分な文字を削除して表示
sort_uniq_data = map(str,uniq_temp)
for temp in sort_uniq_data:
print(''.join(temp).lstrip("['").rstrip("']"))
if __name__ == "__main__":
filename = 'hightemp.txt'
basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
f = codecs.open(filename,'r','utf-8')
sort_uniq(f.readlines())
print('\n')
cut=subprocess.Popen(["cut","-f","1",basepath+filename],stdout=subprocess.PIPE)
sort = subprocess.Popen(["sort"],stdin=cut.stdout,stdout=subprocess.PIPE)
uniq = subprocess.Popen(["uniq"],stdin=sort.stdout,stdout=subprocess.PIPE)
end_of_pipe = uniq.stdout
for line in end_of_pipe:
print(line.decode('utf-8').rstrip('\n'))
千葉県
和歌山県
埼玉県
大阪府
(結果が長いので略)
千葉県
和歌山県
埼玉県
大阪府
山形県
(結果が長いので略)
Process finished with exit code 0
感想:subprocessモジュールを利用したパイプの書き方がわからなかった。。。linuxなら|だけで済むが、プログラムにするとどんなパラメーターが必要かよく分かる。
#018.ソート
各行を3コラム目の数値の降順にソート各行を3コラム目の数値の逆順で整列せよ(注意: 各行の内容は変更せずに並び替えよ).確認にはsortコマンドを用いよ(この問題はコマンドで実行した時の結果と合わなくてもよい).
#-*- conding:utf-8 -*-
import codecs
import subprocess
import operator
def r_sort(data):
cut_temp = []
sort_temp = []
# リスト化
for temp in data:
cut_temp.append(temp.split())
# sortの働き
sort_temp = sorted(cut_temp,key=operator.itemgetter(2),reverse=True)
# listをstrに変換後、余分な文字を削除して表示
sort_data = map(str, sort_temp)
for temp in sort_data:
print(''.join(temp).lstrip("['").rstrip("']"))
if __name__=="__main__":
basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
filename = 'hightemp.txt'
with codecs.open(filename,'r','utf-8') as f:
r_sort(f.readlines())
print('\n')
sort= subprocess.check_output(["sort","-r","-k","3",basepath+filename])
print(sort.decode('utf-8'))
高知県', '江川崎', '41', '2013-08-12
埼玉県', '熊谷', '40.9', '2007-08-16
岐阜県', '多治見', '40.9', '2007-08-16
(結果が長いので略)
高知県 江川崎 41 2013-08-12
岐阜県 多治見 40.9 2007-08-16
埼玉県 熊谷 40.9 2007-08-16
(結果が長いので略)
Process finished with exit code 0
感想:operatorモジュールのitemgetter関数が便利だった。
#019. 各行の1コラム目の文字列の出現頻度を求め,出現頻度の高い順に並べる
各行の1列目の文字列の出現頻度を求め,その高い順に並べて表示せよ.確認にはcut, uniq, sortコマンドを用いよ
#-*- coding:utf-8 -*-
import codecs
import subprocess
import collections
import operator
def frequency(data):
cut_temp = []
sort_temp = []
count_dict={}
# cut -f 1の働き
for temp in data:
cut_temp.append(temp.split()[:1])
# sortの働き
sort_temp = sorted(cut_temp)
#listの中の要素数をカウント
# uniq -c+sortの働き
count_dict = collections.Counter(map(str,sort_temp))
for value,count in sorted(count_dict.items(),key=operator.itemgetter(1),reverse=True):
print(count,str(value).lstrip("['").rstrip("']"))
if __name__=="__main__":
basepath = '/Users/masassy/PycharmProjects/Pywork/training/'
filename = 'hightemp.txt'
with codecs.open(filename,'r','utf-8') as f:
frequency(f.readlines())
print('\n')
cut=subprocess.Popen(["cut","-f","1",basepath+filename],stdout=subprocess.PIPE)
sort1 = subprocess.Popen(["sort"],stdin=cut.stdout,stdout=subprocess.PIPE)
uniq = subprocess.Popen(["uniq","-c"],stdin=sort1.stdout,stdout=subprocess.PIPE)
sort2 = subprocess.Popen(["sort","-r"],stdin=uniq.stdout,stdout=subprocess.PIPE)
end_of_pipe = sort2.stdout
for line in end_of_pipe:
print(line.decode('utf-8').lstrip(' ').rstrip('\n'))
3 山梨県
3 山形県
3 群馬県
3 埼玉県
2 岐阜県
2 千葉県
(結果が長いので略)
3 群馬県
3 山梨県
3 山形県
3 埼玉県
2 静岡県
2 愛知県
(結果が長いので略)
Process finished with exit code 0
感想:辞書型の取扱とソートが難しかった。