awkコマンド 学習メモ

# はじめに
awkコマンドを学習した際のメモ書きを載せております。
awkを軽く理解するためのメモ書きなので、深くまで掘り下げた内容は書いておりません。
ところどころ見づらいかと思いますが、ご了承ください。:bow:

# 組み込み変数
awkにあらかじめ定義されている変数である。
よく使用される組み込み変数は以下の通り

https://qiita.com/yarashi1226/items/ffa1bd8eaa6f3b2f4dc5

| 組み込み変数 | 説明                                    | デフォルト値                       | 
| ------------ | --------------------------------------- | ----------------------------------| 
| $0           | 全て表示                                |                                    | 
| $n           | レコードのn番目のフィールド(数値で指定) |                                    | 
| FILENAME     | ファイル名                              | -                                  | 
| RS           | レコードの区切り文字                    | 改行(\n)                           | 
| FS           | フィールドの区切り文字                  | スペース                           | 
| ORS          | 出力レコードの区切り文字                | 改行(\n)                           | 
| OFS          | 出力フィールドの区切り文字              | 現在の入力ファイル数のレコード数   | 
| NR           | 入力中のレコード数                | 現在の入力ファイル数のレコード数 | 
| NF           | レコード中のフィールド数                | 現在の入力レコード中のフィールド数 | 

# 組み込み関数

http://www.kt.rim.or.jp/~kbk/gawk-30/gawk_13.html

# BEGINとENDについて

awkコマンドには、`'BIGIN{処理内容}'`と`'END{処理内容}'`の2種類が存在する。

- BIGIN：メイン処理を読み取る前に実行される処理
- END：メイン処理が読み終わった後に実行される処理

```
$ awk 'BEGIN { メイン処理を読み取る前に実行される処理 } { メイン処理 } END { メイン処理が読み終わった後に実行される処理 }'
```

```:例
$ awk 'BEGIN{print "<<<始まり>>>"} {print $0} END{print "<<<終わり>>>"}' test.txt 
<<<始まり>>>
abc
123
def
456
ghi
<<<終わり>>>
```

# 列を指定する場合(列区切りがスペースの場合)

Gemini君に生成してもらった:relaxed:

```:テストファイル
Alpha DescriptionA 55 word
Beta ExplanationB 12 text
Gamma DetailC 88 sample
Delta InfoD 33 data
Epsilon NoteE 7 word
Beta SummaryF 91 test
Eta ContentG 27 example
Theta PointH 66 value
Iota ItemI 49 string
Alpha LabelJ 19 number
Lambda MessageK 73 word
Lambda ContextL 3 data
Nu ElementM 99 sample
Xi DetailN 5 text
Omicron ExplanationO 81 value
```

- 全ての列表示 : `awk {'print $0'}`
- 1列目：`awk '{print $1}'`
- 2列目：`awk '{print $2}'`
- 3列目：`awk '{print $3}'`

など

```:例) 1列目の名前を並び替えて重複排除して表示
$ cat test.txt | awk '{print $1}' | sort | uniq
Alpha
Beta
Delta
Epsilon
Eta
Gamma
Iota
Lambda
Nu
Omicron
Theta
Xi
```

### その他解説
- sortコマンド：文字コードごとに並び替え
- uniqコマンド：重複排除

# 列を指定する場合(列区切りがスペース以外の場合)

Gemini君に加工してもらった:relaxed:

```:テストファイル(区切りがセミコロンの場合)
Alpha:DescriptionA:55:word
Beta:ExplanationB:12:text
Gamma:DetailC:88:sample
Delta:InfoD:33:data
Epsilon:NoteE:7:word
Beta:SummaryF:91:test
Eta:ContentG:27:example
Theta:PointH:66:value
Iota:ItemI:49:string
Alpha:LabelJ:19:number
Lambda:MessageK:73:word
Lambda:ContextL:3:data
Nu:ElementM:99:sample
Xi:DetailN:5:text
Omicron:ExplanationO:81:value
```

- 1列目：`awk -F ":" '{print $1}'`
- 2列目：`awk -F ":" '{print $2}'`
- 3列目：`awk -F ":" '{print $3}'`

など

※ awk -F：フィールド区切り文字を指定できる

```:例) 2行目を出力する場合
$ awk -F ":" '{print $2}' test.txt 
DescriptionA
ExplanationB
DetailC
InfoD
NoteE
SummaryF
ContentG
PointH
ItemI
LabelJ
MessageK
ContextL
ElementM
DetailN
ExplanationO
```

# 複数列を指定する場合

このやり方で複数列を指定できるが、見づらくなってしまう
```:例) 1列目、2列目、3列目を出力する場合
$ awk -F ":" '{print $1 $2 $3}' test.txt 
AlphaDescriptionA55
BetaExplanationB12
GammaDetailC88
DeltaInfoD33
EpsilonNoteE7
BetaSummaryF91
EtaContentG27
ThetaPointH66
IotaItemI49
AlphaLabelJ19
LambdaMessageK73
LambdaContextL3
NuElementM99
XiDetailN5
OmicronExplanationO81
```

タブを挿入することで少し見やすくすることができる。

```:例) 1列目、2列目、3列目を出力する場合(タブ区切り)
$ awk -F ":" '{print $1"\t"$2"\t"$3}' test.txt 
Alpha   DescriptionA    55
Beta    ExplanationB    12
Gamma   DetailC 88
Delta   InfoD   33
Epsilon NoteE   7
Beta    SummaryF        91
Eta     ContentG        27
Theta   PointH  66
Iota    ItemI   49
Alpha   LabelJ  19
Lambda  MessageK        73
Lambda  ContextL        3
Nu      ElementM        99
Xi      DetailN 5
Omicron ExplanationO    81
```

スペース区切りで出力することも可能

```:例) 1列目、2列目、3列目を出力する場合(スペース区切り)
$ awk -F ":" '{print $1,$2,$3}' test.txt 
Alpha DescriptionA 55
Beta ExplanationB 12
Gamma DetailC 88
Delta InfoD 33
Epsilon NoteE 7
Beta SummaryF 91
Eta ContentG 27
Theta PointH 66
Iota ItemI 49
Alpha LabelJ 19
Lambda MessageK 73
Lambda ContextL 3
Nu ElementM 99
Xi DetailN 5
Omicron ExplanationO 81
```

好きな記号を利用して区切ることもできる

```:指定方法
$ awk 'BEGIN{FS="変更前の区切り文字"; OFS="変更後の区切り文字"} { $n,$n,$n …… }'
```

```:例) 1列目、2列目、3列目を出力する場合(スラッシュ区切り)
$ awk 'BEGIN{FS=":"; OFS="/"} {print $1,$2,$3}' test.txt 
Alpha/DescriptionA/55
Beta/ExplanationB/12
Gamma/DetailC/88
Delta/InfoD/33
Epsilon/NoteE/7
Beta/SummaryF/91
Eta/ContentG/27
Theta/PointH/66
Iota/ItemI/49
Alpha/LabelJ/19
Lambda/MessageK/73
Lambda/ContextL/3
Nu/ElementM/99
Xi/DetailN/5
Omicron/ExplanationO/81
```

# 特定の行に絞る場合

```:指定方法
$ awk 'NR == 最初の行数, NR == 最後の行数 {処理内容}'
```

```:テストファイルから5行～10行を抽出して表示
$ awk 'NR == 5, NR == 10 {print NR,$0}' test.txt
5 Epsilon NoteE 7 word
6 Beta SummaryF 91 test
7 Eta ContentG 27 example
8 Theta PointH 66 value
9 Iota ItemI 49 string
10 Alpha LabelJ 19 number
```

# [小技編] 指定したプロセスを全てkillするコマンド

https://qiita.com/ymatsukawa/items/f6d0c02f61a4ad9cd9b4

```:指定方法
ps aux | grep プロセス名 | grep -v grep | awk '{print $2}' | xargs -I {} kill {}
```

```:指定したプロセスを全て強制終了させる
ps aux | grep プロセス名 | grep -v grep | awk '{print $2}' | xargs -I {} kill -9 {}
```

まぁ、pgrepかpkill使えばいいんですけどね:pensive:

- pgrepコマンド：プロセス名やユーザー、グループ、端末名などからプロセスIDを探すコマンド
- pkillコマンド：プロセス名を指定して、終了シグナルなどのシグナルを送信するコマンド

# 条件分岐を利用する場合

### if文
```:if文の指定方法
# awk '{if(条件式) {True処理}}'
```

大体grepでいいが、特定の列名を指定したい時には使えるかも...

```:例) apacheのみのレコードを出力する場合(※PS情報は加工してある)
# ps auxww | awk '{if($1 == "apache") {print $0}}'
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
apache       xxxx 0.0  0.0  xxxxxx  xxxxxx x        x    xx:xx   0:00 xxxxxxxxxxxxxx
```

### if else文

```:if else文の指定方法
# awk '{if(条件式) {True処理} else {False処理}}'
```

このテストファイルを利用する
```:テストファイル
Alpha DescriptionA 55 word
Beta ExplanationB 12 text
Gamma DetailC 88 sample
Delta InfoD 33 data
Epsilon NoteE 7 word
Beta SummaryF 91 test
Eta ContentG 27 example
Theta PointH 66 value
Iota ItemI 49 string
Alpha LabelJ 19 number
Lambda MessageK 73 word
Lambda ContextL 3 data
Nu ElementM 99 sample
Xi DetailN 5 text
Omicron ExplanationO 81 value
```

```:例) 1列がBetaのレコードは出力し、それ以外は"Not matching"を出力
$ awk '{if($1 == "Beta") {print $0} else {print "Not matching"}}' test.txt 
Not matching
Beta ExplanationB 12 text
Not matching
Not matching
Not matching
Beta SummaryF 91 test
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
```

### 三項演算子でも表現可能

```:三項演算子の指定方法
条件式 ? True処理 : False処理
```

```
$ awk '{print $1 == "Beta" ? $0 : "Not matching"}' test.txt 
Not matching
Beta ExplanationB 12 text
Not matching
Not matching
Not matching
Beta SummaryF 91 test
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
Not matching
```

# 繰り返し文を利用する場合

```:for文の指定方法
# awk 'BEGIN{for(i = 1; i < x; i++) 処理内容}'
```

```:平方根を出力
# awk 'BEGIN{for(i = 1; i <= 10; i++) print i,"の平方根は",i*i;}'
1 の平方根は 1
2 の平方根は 4
3 の平方根は 9
4 の平方根は 16
5 の平方根は 25
6 の平方根は 36
7 の平方根は 49
8 の平方根は 64
9 の平方根は 81
10 の平方根は 100
```

※while文などは割愛

# さいごに
所感：プログラミング言語なんだなぁ

# 参考資料
- [IBM ドキュメント 7.2 awk コマンド](https://www.ibm.com/docs/ja/aix/7.2?topic=awk-command)
- [Learning Awk Is Essential For Linux Users](https://www.youtube.com/watch?v=9YOZmI-zWok)
- [とほほのAWK入門](https://www.tohoho-web.com/ex/awk.html)
- [[初心者向け]Awkの使い方](https://qiita.com/tofu511/items/3ecf9c5361d08b5c6eae)
- [AWKコマンドを使う上で使う組み込み変数](https://qiita.com/yarashi1226/items/ffa1bd8eaa6f3b2f4dc5)