「言語処理100本ノック 2015」ではじめるPythonとNLPスキルのリハビリテーション（第2章前半）

前回の更新から1か月近く・・・順調な三日坊主ぶりです。

このへんは、章のタイトルの通りUNIXコマンドを使ってやることが多いので、
pythonで書けと言われると少し面倒に感じるかも。

まずは、データセットをダウンロードして・・・。

# 第2章: UNIXコマンドの基礎

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

```py:
filename = 'hightemp.txt'
f = open(filename, 'r')
print sum([1 for l in f])
#>>> 24
```

これは本当にいろんな方法があるようで・・・。
http://551sornwmc.blog109.fc2.com/blog-entry-387.html
http://stackoverflow.com/questions/845058/how-to-get-line-count-cheaply-in-python

メモリ使用量と実行速度の点では、こちらのメモリマップドファイルを使うのが良さそう。

```py:
# using memory mapped file
import mmap
def mapcount(filename):
    f = open(filename, "r+")
    buf = mmap.mmap(f.fileno(), 0)
    lines = 0
    readline = buf.readline
    while readline():
        lines += 1
    return lines
```

UNIXコマンドでの確認はこちら。

```bash:
wc -l hightemp.txt
#>>> 24
```


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

```py:
#import re

filename = 'hightemp.txt'
f = open(filename, 'r')
lines = f.readlines()
for line in lines:
    #line_replaced =  re.sub(r'\t', r'\s', line)
    line_replaced = line.expandtabs(1)
    print line_replaced,
```

[expandtabs](https://docs.python.org/2.7/library/string.html#string.expandtabs)なんてあるんだ。

UNIXコマンドでの確認はこちら。

```bash:
cat hightemp.txt | tr '\t' ','
```
これ↑が一番すんなりできそう。

```bash:
sed -e s/'\t'/'\s'/g hightemp.txt
#Macでうまくいかないので、あらため
sed -e s/$'\t'/$'\s'/g hightemp.txt
#あれ？
```

http://mattintosh.hatenablog.com/entry/2013/01/16/143323
>Mac OS X などに入っている BSD sed は echo や printf のようにスクリプト中の \t をタブには展開しません。

Oh...


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

```py:
filename = 'hightemp.txt'
filename_col1 = 'col1.txt'
filename_col2 = 'col2.txt'

f = open(filename, 'r')
f_col1 = open(filename_col1, 'w')
f_col2 = open(filename_col2, 'w')

lines = f.readlines()

content_col1 = [line.split()[0] + '\n' for line in lines]
content_col2 = [line.split()[1] + '\n' for line in lines]

f_col1.writelines(content_col1)
f_col2.writelines(content_col2)

f_col1.close()
f_col2.close()
```

一点注意としては、writelines メソッドでは改行が入らないので、
自分で追加してあげたことでしょうか。

UNIXコマンドでの確認はこちら。
うわー吐き気がするほど簡単。

```bash:
cut -f1 hightemp.txt > col1.txt
cut -f2 hightemp.txt > col2.txt
```

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

```py:
filename_col1 = 'col1.txt'
filename_col2 = 'col2.txt'
filename_col1_col2 = 'col1_col2.txt'

f_col1 = open(filename_col1, 'r')
f_col2 = open(filename_col2, 'r')
f_col1_col2 = open(filename_col1_col2, 'w')

lines_1 = f_col1.readlines()
lines_2 = f_col2.readlines()

content = [line1 + '\t' + line2 + '\n' for line1, line2 in zip(lines_1, lines_2)]

f_col1_col2.writelines(content)
f_col1_col2.close()    

f_col1.close()    
f_col2.close()    

```


UNIXコマンドでの確認はこちら。
簡単すぎて吐いちゃった。

```bash:
paste col1.txt col2.txt > col1_col2.txt
```


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

```py:knock014.py
# -*- coding: utf-8 -*-

import sys
import argparse

parser = argparse.ArgumentParser(description='Head command. Accepts an integer and a file name.')

# 行数
parser.add_argument(
	'-l', '--line',
	type = int,
	dest = 'line',
	default = 10,
	help = 'headコマンドで指定する行数に相当'
)

# ファイル名
parser.add_argument(
    '-f', '--filename',
    type = str,						# 受け取る値の型を指定する
    dest = 'filename',     			# 保存先変数名
    required = True,    			# 必須項目
    help = '入力として与えるファイル名'	# --help時に表示する文
)

args = parser.parse_args()
N = args.line
filename = args.filename

# 先頭のN行を表示する
f = open(filename)
for x in xrange(N):
	print f.next().strip()
f.close()
```

上記を実行すると。

```py:
python knock014.py -l 3 -f hightemp.txt
# >>>高知県	江川崎	41	2013-08-12
# >>>埼玉県	熊谷	40.9	2007-08-16
# >>>岐阜県	多治見	40.9	2007-08-16

python knock014.py -l 3 -f 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
# >>>和歌山県	かつらぎ	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
```

UNIXコマンドでの確認はこちら。

```bash:
head -3 hightemp.txt

head hightemp.txt
```

## 15. 末尾のN行を出力
> 自然数Nをコマンドライン引数などの手段で受け取り，入力のうち末尾のN行だけを表示せよ．確認にはtailコマンドを用いよ．

```py:knock015.py
# -*- coding: utf-8 -*-

import sys
import argparse

parser = argparse.ArgumentParser(description='Tail command. Accepts an integer and a file name.')

# 行数
parser.add_argument(
	'-l', '--line',
	type = int,
	dest = 'line',
	default = 10,
	help = 'tailコマンドで指定する行数に相当'
)

# ファイル名
parser.add_argument(
    '-f', '--filename',
    type = str,						# 受け取る値の型を指定する
    dest = 'filename',     			# 保存先変数名
    required = True,    			# 必須項目
    help = '入力として与えるファイル名'	# --help時に表示する文
)

args = parser.parse_args()
N = args.line
filename = args.filename

# 最後のN行を表示する
f = open(filename)
lines = f.readlines()
M = len(lines)

for i, line in enumerate(lines):
	if i+N >= M:
		#print i
		print line.strip()

f.close()
```

基本的には、14.から最後の処理を少し変えただけです。
UNIXコマンドでの確認はこちら。

```bash:
tail -3 hightemp.txt

tail hightemp.txt
```