自然言語処理100本ノック 第2章 UNIXコマンドの基礎(前半)


第2章の前半の問題を解いた記録。
UNIXコマンドでの実行結果も併記。

対象とするファイルはwebページにもある通り、hightemp.txtとする。

hightemp.txtは,日本の最高気温の記録を「都道府県」「地点」「℃」「日」のタブ区切り形式で格納したファイルである.以下の処理を行うプログラムを作成し,hightemp.txtを入力ファイルとして実行せよ.さらに,同様の処理をUNIXコマンドでも実行し,プログラムの実行結果を確認せよ.

10. 行数のカウント

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

# -*- coding: utf-8 -*-
__author__ = 'todoroki'

f = open('hightemp.txt')
lines = f.readlines()
print len(lines)
f.close()

#=> 24

対象ファイルを行ごとに読み込み、その行数を数える。

cat hightemp.txt | grep -c ""

#=> 24

cat でテキストを表示しそれをパイプで grep に渡して行数を数える。
ちなみに、パイプの後ろの grep -c "" ではなくて wc -l でも同じように行数を数えることができるが、 wc の場合は出力にスペースが加わってしまう。
行数の出力をパイプで他の処理に渡す場合にスペースが含まれていると邪魔な場合があるので、 grep -c "" を使うほうがよい場合が多いと思われる。

11. タブをスペースに置換

タブ1文字につきスペース1文字に置換せよ.確認にはsedコマンド,trコマンド,もしくはexpandコマンドを用いよ.

# -*- coding: utf-8 -*-
__author__ = 'todoroki'

import re

inputfile = 'hightemp.txt'
outputfile = 'hightemp_tab2space.txt'

f = open(inputfile)
lines = f.readlines()
g = open(outputfile, 'w')
for line in lines:
    line = re.sub('\t', ' ', line)
    g.write(line)
    print line
f.close()
g.close()

#=> 高知県 江川崎 41 2013-08-12
#=> 埼玉県 熊谷 40.9 2007-08-16
#=> 岐阜県 多治見 40.9 2007-08-16
#=> 山形県 山形 40.8 1933-07-25
#=> 山梨県 甲府 40.7 2013-08-10
#=> 和歌山県 かつらぎ 40.6 1994-08-08
#=> 静岡県 天竜 40.6 1994-08-04
#=> 山梨県 勝沼 40.5 2013-08-10
#=> 埼玉県 越谷 40.4 2007-08-16
#=> 群馬県 館林 40.3 2007-08-16
#=> 群馬県 上里見 40.3 1998-07-04
#=> 愛知県 愛西 40.3 1994-08-05
#=> 千葉県 牛久 40.2 2004-07-20
#=> 静岡県 佐久間 40.2 2001-07-24
#=> 愛媛県 宇和島 40.2 1927-07-22
#=> 山形県 酒田 40.1 1978-08-03
#=> 岐阜県 美濃 40 2007-08-16
#=> 群馬県 前橋 40 2001-07-24
#=> 千葉県 茂原 39.9 2013-08-11
#=> 埼玉県 鳩山 39.9 1997-07-05
#=> 大阪府 豊中 39.9 1994-08-08
#=> 山梨県 大月 39.9 1990-07-19
#=> 山形県 鶴岡 39.9 1978-08-03
#=> 愛知県 名古屋 39.9 1942-08-02

タブ文字 \t を空白に置換する。

cat hightemp.txt | tr "\t" " " > hightemp_tr.txt

#=> (出力は上と同じ)

12. 1列目をcol1.txtに,2列目をcol2.txtに保存

各行の1列目だけを抜き出したものをcol1.txtに,2列目だけを抜き出したものをcol2.txtとしてファイルに保存せよ.確認にはcutコマンドを用いよ.

# -*- coding: utf-8 -*-
__author__ = 'todoroki'

inputfile = 'hightemp.txt'
outputfile1 = 'col1.txt'
outputfile2 = 'col2.txt'
f = open(inputfile)
lines = f.readlines()
g = open(outputfile1, "w")
h = open(outputfile2, "w")
for line in lines:
    line = line.split('\t')
    g.write(line[0].strip('\n') + '\n')
    h.write(line[1].strip('\n') + '\n')
f.close()
g.close()
h.close()

# (col1.txt)
#=> 高知県
#=> 埼玉県
#=> 岐阜県
#=> 山形県
#=> 山梨県
#=> 和歌山県
#=> 静岡県
#=> 山梨県
#=> 埼玉県
#=> 群馬県
#=> 群馬県
#=> 愛知県
#=> 千葉県
#=> 静岡県
#=> 愛媛県
#=> 山形県
#=> 岐阜県
#=> 群馬県
#=> 千葉県
#=> 埼玉県
#=> 大阪府
#=> 山梨県
#=> 山形県
#=> 愛知県

# (col2.txt)
#=> 江川崎
#=> 熊谷
#=> 多治見
#=> 山形
#=> 甲府
#=> かつらぎ
#=> 天竜
#=> 勝沼
#=> 越谷
#=> 館林
#=> 上里見
#=> 愛西
#=> 牛久
#=> 佐久間
#=> 宇和島
#=> 酒田
#=> 美濃
#=> 前橋
#=> 茂原
#=> 鳩山
#=> 豊中
#=> 大月
#=> 鶴岡
#=> 名古屋

タブ区切りでsplitして対象をそれぞれファイルに出力

cut -f 1 hightemp.txt > hightemp_cut1.txt
cut -f 2 hightemp.txt > hightemp_cut2.txt

#=> (上と同じため出力を省略)

13. col1.txtとcol2.txtをマージ

12で作ったcol1.txtとcol2.txtを結合し,元のファイルの1列目と2列目をタブ区切りで並べたテキストファイルを作成せよ.確認にはpasteコマンドを用いよ.

# -*- coding: utf-8 -*-
__author__ = 'todoroki'

inputfile1 = 'col1.txt'
inputfile2 = 'col2.txt'
outputfile = 'col_merge.txt'

f = open(inputfile1)
g = open(inputfile2)
h = open(outputfile, "w")

lines1 = f.readlines()
lines2 = g.readlines()
for a, b in zip(lines1, lines2):
    h.write(a.strip() + '\t' + b.strip() + '\n')
f.close()
g.close()
h.close()

#=> 高知県   江川崎
#=> 埼玉県   熊谷
#=> 岐阜県   多治見
#=> 山形県   山形
#=> 山梨県   甲府
#=> 和歌山県    かつらぎ
#=> 静岡県   天竜
#=> 山梨県   勝沼
#=> 埼玉県   越谷
#=> 群馬県   館林
#=> 群馬県   上里見
#=> 愛知県   愛西
#=> 千葉県   牛久
#=> 静岡県   佐久間
#=> 愛媛県   宇和島
#=> 山形県   酒田
#=> 岐阜県   美濃
#=> 群馬県   前橋
#=> 千葉県   茂原
#=> 埼玉県   鳩山
#=> 大阪府   豊中
#=> 山梨県   大月
#=> 山形県   鶴岡
#=> 愛知県   名古屋

2つのファイルを読み込み、zip関数でシーケンスオブジェクトを並行して処理。

paste col1.txt col2.txt > hightemp_paste.txt

#=> (出力は上と同じ)

14. 先頭からN行を出力

自然数Nをコマンドライン引数などの手段で受け取り,入力のうち先頭のN行だけを表示せよ.確認にはheadコマンドを用いよ.

# -*- coding: utf-8 -*-
__author__ = 'todoroki'

import sys

if len(sys.argv) == 3:
    N = int(sys.argv[1])
    f = open(sys.argv[2])
    lines = f.readlines()
    for i in xrange(N):
        print lines[i].strip()
    f.close()
else:
    print "please input \'N\' and \'FILENAME\'"

# (python problem14.py 5 hightemp.txt)
#=> 高知県     江川崎     41      2013-08-12
#=> 埼玉県     熊谷      40.9    2007-08-16
#=> 岐阜県     多治見     40.9    2007-08-16
#=> 山形県     山形      40.8    1933-07-25
#=> 山梨県     甲府      40.7    2013-08-10

受け取った行数だけ読み取った行を出力する。

head -n 5 hightemp.txt

#=> (出力は上と同じ)