言語処理１００本ノック２０２０やってみた　part2

#はじめに
[言語処理１００本ノック２０２０やってみた part1](URL:https://qiita.com/KawabataK/items/18322b538c9912e08867)

* コマンドの説明は自分の解釈なのであしからず

#目次
###第2章: UNIXコマンド
[事前準備](#事前準備)
[10. 行数のカウント](#10-行数のカウント)
[11. タブをスペースに置換](#11-タブをスペースに置換)
[12. 1列目をcol1.txtに，2列目をcol2.txtに保存](#12-1列目をcol1txtに2列目をcol2txtに保存)
[13. col1.txtとcol2.txtをマージ](#13-col1txtとcol2txtをマージ)
[14. 先頭からN行を出力](#14-先頭からN行を出力)
[15. 末尾のN行を出力](#15-末尾のn行を出力)
[16. ファイルをN分割する](#16-ファイルをn分割する)
[17. １列目の文字列の異なり](#17-１列目の文字列の異なり)
[18. 各行を3コラム目の数値の降順にソート](#18-各行を3コラム目の数値の降順にソート)
[19. 各行の1コラム目の文字列の出現頻度を求め，出現頻度の高い順に並べる](#19-各行の1コラム目の文字列の出現頻度を求め出現頻度の高い順に並べる)
[感想](#感想)

#事前準備
[第2章: UNIXコマンド](URL:https://nlp100.github.io/ja/ch02.html)の課題をこなすために`popular-names.txt`をダウンロードする必要があります。このファイルは`https://nlp100.github.io/data/popular-names.txt`にあるので`wget`コマンド使ってダウンロードします。

* [google colab](URL:)でコマンド実行するためには先頭に`!`を付けます。
* 各課題で`|`がよく出てきます。これは複数コマンドを同時に行う時に使用して左から順に実行します

```
!wget https://nlp100.github.io/data/popular-names.txt
```
```:確認
! ls
popular-names.txt  sample_data
```
```:中身
! head ./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
```


[【 wget 】コマンド――URLを指定してファイルをダウンロードする](URL:https://www.atmarkit.co.jp/ait/articles/1606/20/news024.html)

#10. 行数のカウント
>行数をカウントせよ．確認にはwcコマンドを用いよ．
[【 wc 】コマンド――テキストファイルの文字数や行数を数える]

| コマンド| オプション| 効果 |
|:-:|:-:|:-:|
|  wc |  --line  | 指定ファイルの行数表示  |

```
!wc --lines ./popular-names.txt
```
```:出力
2780 ./popular-names.txt
```


* [【 wc 】コマンド――テキストファイルの文字数や行数を数える](URL:https://www.atmarkit.co.jp/ait/articles/1611/07/news026.html)



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

#####コメント
`s/正規表現で置換される語を指定/置換する語/g (s/ / /g)`とすれば一つの文の中で指定した正規表現と一致した語は全て置換される
>[パターンマッチと文字列置換](URL:http://7ujm.net/Perl/perl2.html)
> 文字列 =~ s/正規表現で書かれたパターン/置換する文字列/
,/g   複数の文字を入れ替えるオプション

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
| sed  | -e スクリプト  | スクリプトで書かれたことを実行  |

```
!sed -e 's/\t/ /g' ./popular-names.txt | head
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
```

* [【 sed 】コマンド（基礎編）――テキストファイルを編集する](URL:https://www.atmarkit.co.jp/ait/articles/1610/06/news021.html#:~:text=sed%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%A8%E3%81%AF%EF%BC%9F,%E3%81%AE%E3%81%8C%E4%B8%80%E8%88%AC%E7%9A%84%E3%81%A7%E3%81%99%E3%80%82)
* [【 tr 】コマンド――テキストファイルの文字を置換する／削除する](URL:https://www.atmarkit.co.jp/ait/articles/1610/03/news017.html)
* [【 expand 】コマンド／【 unexpand 】コマンド――タブと空白を変換する](URL:https://www.atmarkit.co.jp/ait/articles/1611/02/news023.html)
* [コマンドでtabやスペースを置換する方法](URL:https://takuya-1st.hatenablog.jp/entry/2014/08/04/152101)
* [sed でタブを入力するには？](URL:https://mattintosh.hatenablog.com/entry/2013/01/16/143323)
* [sedでスペースをタブに置換 (連続スペースは1文字とみなす)](URL:http://luvtome.blog5.fc2.com/blog-entry-647.html)
* [・歴史資料のデジタル加工入門
大量置換のためのツール sed を用いて　その1【文学・歴史資料のデジタル加工入門10】 （木越 治）](URL:https://company.books-yagi.co.jp/archives/3175/3)

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

#####コメント
[13. col1.txtとcol2.txtをマージ](#13-col1txtとcol2txtをマージ)をやってる時にコマンドで加工したテキストをファイルに出力する方法を知ったからそれ使えばpython使わなくてもよかった。もったいないので残します。

```py
path = "./popular-names.txt"
with open(path,"r") as f:
  col1 = []
  col2 = []
  lines=f.readlines()

  for line in lines:
    processed_line = line.strip().split('\t')
    col1.append(processed_line[0])
    col2.append(processed_line[1])

with open('col1.txt','x') as f:
  f.write('\n'.join(col1))

with open('col2.txt','x') as f:
  f.write('\n'.join(col2))
```
<br>

| コマンド| オプション | 効果 |
|:-:|:-:|:-:|
|  cut | -f 数字 | 指定した数字の列のみ取り出す（始まりは１）  |

```
! cut -f 1 > ./col1.txt | head -n 5
Mary
Anna
Emma
Elizabeth
Minnie
```

```
! cut -f 2 > ./col2.txt | head　-n 5
F
F
F
F
F
```


* [【 cut 】コマンド――行から固定長またはフィールド単位で切り出す](URL:https://www.atmarkit.co.jp/ait/articles/1610/31/news026.html)
* [Pythonでファイルの読み込み、書き込み（作成・追記](URL:https://note.nkmk.me/python-file-io-open-with/)

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

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
|  paste | -d 結合文字  | 指定したファイルを結合文字で繋ぐ（今回はtab（\t）） |

```
! paste -d '\t' col1.txt col2.txt > col1col2.txt | head -n 5
Mary	F
Anna	F
Emma	F
Elizabeth	F
Minnie	F
```

* [【 paste 】コマンド――複数のファイルを行単位で連結する](URL:https://www.atmarkit.co.jp/ait/articles/1704/07/news018.html)
* [paste コマンド](URL:https://www.ibm.com/support/knowledgecenter/ja/ssw_aix_71/p_commands/paste.html)

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

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
|  head | -n　数字  | 指定ファイルの先頭から`数字`だけ行を出力（`-n`を付けなければ10行）  |

```
! head -n 5 ./col1col2.txt
Mary	F
Anna	F
Emma	F
Elizabeth	F
Minnie	F
```

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

`head`とほぼ同じなので解説は割愛

```
! tail -n 5 ./col1col2.txt
Benjamin	M
Elijah	M
Lucas	M
Mason	M
Logan	M
```

* [tailコマンドについて詳しくまとめました 【Linuxコマンド集】](URL:https://eng-entrance.com/linux-command-tail)

#16. ファイルをN分割する
>自然数Nをコマンドライン引数などの手段で受け取り，入力のファイルを行単位でN分割せよ．同様の処理をsplitコマンドで実現せよ．

#####コメント

* popular-names.txtは2780行ある。今回は500行づつ分割するのでファイルは６つできる
* `ls comb-*`でcomb-とつくファイルを全て調べている

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
|  split |  -l [数字] [分割するファイル] [分割したあとのファイル名の元]| [数字]行づつ分割してファイル作成（ファイル名は自動で作られる）  |


```

! split -l 500 ./col1col2.txt comb- | ls comb-*
comb-aa  comb-ab  comb-ac  comb-ad  comb-ae  comb-af
```

* [【 split 】コマンド――ファイルを分割する](URL:https://www.atmarkit.co.jp/ait/articles/1711/24/news016.html)

#17. １列目の文字列の異なり
>1列目の文字列の種類（異なる文字列の集合）を求めよ．確認にはcut, sort, uniqコマンドを用いよ．

#####コメント
あってるのかわからん

| コマンド| オプション | 効果 |
|:-:|:-:|:-:|
|  cut | -f [数字] [対象ファイル]| 指定した[数字]の列のみ取り出す（始まりは１）  |
|sort|-d [対象ファイル]|ファイル内のデータが空白と英数字の場合ソート（文字はアルファベット順ぽい） |
|uniq|[対象ファイル]|オプションがない場合各行の要素を重複を無くしてくれる|

#####流れ
`popular-names.txt`の１列目に注目、アルファベット順にソート、同じ名前のものは一つにまとめる

```
! cut -f 1 ./popular-names.txt | sort -d | uniq | head -n 5
Abigail
Aiden
Alexander
Alexis
Alice
```

* [【 cut 】コマンド――行から固定長またはフィールド単位で切り出す](URL:https://www.atmarkit.co.jp/ait/articles/1610/31/news026.html) 
* [【 sort 】コマンド――テキストファイルを行単位で並べ替える] (URL:atmarkit.co.jp/ait/articles/1611/09/news020.html#sample1)
* [uniqコマンドについて詳しくまとめました 【Linuxコマンド集】](URL:https://eng-entrance.com/linux-command-uniq)


#18. 各行を3コラム目の数値の降順にソート
>各行を3コラム目の数値の逆順で整列せよ（注意: 各行の内容は変更せずに並び替えよ）．確認にはsortコマンドを用いよ（この問題はコマンドで実行した時の結果と合わなくてもよい）．

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
|sort|-k [数字] [ファイル]|[数字]の列に注目してソート|
||-r [ファイル]|ファイルを逆から表示する|

```
! sort -k 3 -r ./popular-names.txt | head -n 5
Linda	F	99689	1947
James	M	9951	1911
Mildred	F	9921	1913
Mary	F	9889	1886
Mary	F	9888	1887
```

#19. 各行の1コラム目の文字列の出現頻度を求め，出現頻度の高い順に並べる
>各行の1列目の文字列の出現頻度を求め，その高い順に並べて表示せよ．確認にはcut, uniq, sortコマンドを用いよ.

#####コメント
* `uniq`コマンドを使う前にsortしなければならない

| コマンド | オプション | 効果 |
|:-:|:-:|:-:|
|sort|-k [数字] [ファイル]|[数字]の列に注目してソート|
||-r [ファイル]|ファイルを逆から表示する(sortしていたら(降順（大きい数から）))|
||-g [ファイル]|数値の並べ替え（昇順（小さい数から））|
|uniq|-c [ファイル]|重複している文字列を数える|

```:失敗例　uniqコマンドを先に実行してしまった場合
! cut -f 1 ./popular-names.txt | uniq -c | sort -r | head -n 5¥
      1 William
      1 William
      1 William
      1 William
      1 William
```
```
! cut -f 1 ./popular-names.txt | sort -d | uniq -c | sort -k 1 -g -r | head -n 10
    118 James
    111 William
    108 Robert
    108 John
     92 Mary
     75 Charles
     74 Michael
     73 Elizabeth
     70 Joseph
     60 Margaret
```

#感想
UNIXコマンドが便利すぎてびっくりした。わざわざコード組まなくていいじゃん