第2章: UNIXコマンド¶

popular-names.txtは、アメリカで生まれた赤ちゃんの「名前」「性別」「人数」「年」をタブ区切り形式で格納したファイルである。以下の処理を行うプログラムを作成し、popular-names.txtを入力ファイルとして実行せよ。さらに、同様の処理をUNIXコマンドでも実行し、プログラムの実行結果を確認せよ。

10. 行数のカウント¶

ファイルの行数をカウントせよ。確認にはwcコマンドを用いよ。

In [26]:
with open("../data/popular-names.txt", "r") as f:
    lines = f.readlines()
    print(len(lines))
2780
In [18]:
# brew install tlrc
# tldr wc
!wc -l ../data/popular-names.txt
    2780 ../data/popular-names.txt

11. 先頭からN行を出力¶

ファイルの先頭N行だけを表示せよ。例えば、N=10として先頭10行を表示せよ。確認にはheadコマンドを用いよ。

In [2]:
def print_head(path: str, n: int):
    with open(path, "r") as f:
        lines = f.readlines()
        for l in lines[:n]:
            print(l, end="")
print_head("../data/popular-names.txt", 10)
Mary	F	7065	1880
Anna	F	2604	1880
Emma	F	2003	1880
Elizabeth	F	1939	1880
Minnie	F	1746	1880
Margaret	F	1578	1880
Ida	F	1472	1880
Alice	F	1414	1880
Bertha	F	1320	1880
Sarah	F	1288	1880
In [1]:
!head -10 ../data/popular-names.txt
Mary	F	7065	1880
Anna	F	2604	1880
Emma	F	2003	1880
Elizabeth	F	1939	1880
Minnie	F	1746	1880
Margaret	F	1578	1880
Ida	F	1472	1880
Alice	F	1414	1880
Bertha	F	1320	1880
Sarah	F	1288	1880

12. 末尾のN行を出力¶

ファイルの末尾N行だけを表示せよ。例えば、N=10として末尾10行を表示せよ。確認にはtailコマンドを用いよ。

In [4]:
def print_tail(path: str, n: int):
    with open(path, "r") as f:
        lines = f.readlines()
        for l in lines[-n:]:
            print(l, end="")
print_tail("../data/popular-names.txt", 10)
Liam	M	19837	2018
Noah	M	18267	2018
William	M	14516	2018
James	M	13525	2018
Oliver	M	13389	2018
Benjamin	M	13381	2018
Elijah	M	12886	2018
Lucas	M	12585	2018
Mason	M	12435	2018
Logan	M	12352	2018
In [5]:
!tail -10 ../data/popular-names.txt
Liam	M	19837	2018
Noah	M	18267	2018
William	M	14516	2018
James	M	13525	2018
Oliver	M	13389	2018
Benjamin	M	13381	2018
Elijah	M	12886	2018
Lucas	M	12585	2018
Mason	M	12435	2018
Logan	M	12352	2018

13. タブをスペースに置換¶

ファイルの先頭10行に対して、タブ1文字につきスペース1文字に置換して出力せよ。確認にはsedコマンド、trコマンド、もしくはexpandコマンドなどを用いよ。

In [7]:
with open("../data/popular-names.txt", "r") as f:
    lines = f.readlines()
    for l in lines[:10]:
        print(" ".join(l.split("	")), end="")
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
Elizabeth F 1939 1880
Minnie F 1746 1880
Margaret F 1578 1880
Ida F 1472 1880
Alice F 1414 1880
Bertha F 1320 1880
Sarah F 1288 1880
In [ ]:
!head -10 ../data/popular-names.txt | sed 's/	/ /g'
Mary F 7065 1880
Anna F 2604 1880
Emma F 2003 1880
Elizabeth F 1939 1880
Minnie F 1746 1880
Margaret F 1578 1880
Ida F 1472 1880
Alice F 1414 1880
Bertha F 1320 1880
Sarah F 1288 1880

14. 1列目を出力¶

ファイルの先頭10行に対して、各行の1列目だけを抜き出して表示せよ。確認にはcutコマンドなどを用いよ。

In [9]:
with open("../data/popular-names.txt", "r") as f:
    lines = f.readlines()[:10]
    for l in lines:
        print(l.split("	")[0])
Mary
Anna
Emma
Elizabeth
Minnie
Margaret
Ida
Alice
Bertha
Sarah
In [11]:
!head -10 ../data/popular-names.txt | cut -f -1
Mary
Anna
Emma
Elizabeth
Minnie
Margaret
Ida
Alice
Bertha
Sarah

15. ファイルをN分割する¶

ファイルを行単位でN分割し、別のファイルに格納せよ。例えば、N=10としてファイルを10分割せよ。同様の処理をsplitコマンドで実現せよ。

In [20]:
def split_to_n(path: str, n: int):
    with open(path, "r") as f:
        lines = f.readlines()

    each = []
    per = (len(lines) + 1) // n
    for i in range(0, n):
        each.append(lines[i:i+per])

    for i, e in enumerate(each):
        with open(f"../junk/{i}.txt", "w") as f:
            f.writelines(e)

split_to_n("../data/popular-names.txt", 10)
In [15]:
!tldr split
warning: 1 page(s) found for other platforms:
1. common (tldr --platform common split)

  split

  Split a file into pieces.
  More information: https://keith.github.io/xcode-man-pages/split.1.html.

  Split a file, each split having 10 lines (except the last split):

    split -l 10 path/to/file

  Split a file by a regex. The matching line will be the first line of the next
  output file:

    split -p cat|^[dh]og path/to/file

  Split a file with 512 bytes in each split (except the last split; use 512k for
  kilobytes and 512m for megabytes):

    split -b 512 path/to/file

  Split a file into 5 files. File is split such that each split has same size
  (except the last split):

    split -n 5 path/to/file

In [21]:
%%bash
N=10
lcount=$(wc -l < ../data/popular-names.txt)
per=$(( (lcount + N - 1) / N ))   # 向上取整,保证正好 N 份
split -l "$per" ../data/popular-names.txt ../junk/

16. ランダムに各行を並び替える¶

ファイルを行単位でランダムに並び替えよ(注意: 各行の内容は変更せずに並び替えよ)。同様の処理をshufコマンドで実現せよ。

In [ ]:
 

17. 1列目の文字列の異なり¶

1列目の文字列の異なり(文字列の種類)を求めよ。確認にはcut, sort, uniqコマンドを用いよ。

18. 各行の1列目の文字列の出現頻度を求め、出現頻度の高い順に並べる¶

1列目の文字列の出現頻度を求め、出現頻度と名前を出現頻度の多い順に並べて表示せよ。確認にはcut, uniq, sortコマンドを用いよ。

19. 3列目の数値の降順に各行を並び替える¶

3列目の数値の逆順でファイルの各行を整列せよ(注意: 各行の内容は変更せずに並び替えよ)。同様の処理をsortコマンドで実現せよ。