awkワンライナー メモ

* 1列目と3列目のみ表示

```bash
$ awk '{print $1,$3}'
```
* 末尾から3列目を表示

```bash
$ awk '{print $(NF - 2)}'
```

* 区切り文字を","として1列目のみ表示

```bash
$ awk -F, '{print $1}'
```
* 1列目と3列目以外を表示(行頭、行末に無駄な空白を入れずに)

```bash
$ awk '{for(i=1;i<=NF;i++) if(i!=1 && i!=3) printf (i>2 ? OFS : "") $i ; printf "\n"}'
```

* 一行目のヘッダが特定の文字列から始まる列のみ表示(行頭、行末に無駄な空白を入れずに) 

```bash
# 一行目のヘッダが"hoge"から始まる列のみ表示(行頭、行末に無駄な空白を入れずに)
$ awk 'NR==1 {for(i=1;i<=NF;i++) if($i~/^hoge/) a[i]=1} {s=0; for(i=1;i<=NF;i++) if(a[i]) printf (s++ ? OFS : "") $i ; printf "\n"} '

# 以下は例
$ cat test5.txt
foo1 hoge2 bar3 hoge4 foo5
1 2 3 4 5
a b c d e
$ awk 'NR==1 {for(i=1;i<=NF;i++) if($i~/^hoge/) a[i]=1} {s=0; for(i=1;i<=NF;i++) if(a[i]) printf (s++ ? OFS : "") $i ; printf "\n"} ' test5.txt
hoge2 hoge4
2 4
b d
```

* 特定のパターンにマッチする行のみ表示

```bash
# hogehogeにマッチする行を表示
$ awk '/hogehoge/' 
$ awk '$0 ~ /hogehoge/' 
$ awk '{if($0~/hogehoge/) print}' 
```

* 空行をスキップする

```bash
$ awk 'NF' 
$ awk '/./' 
$ awk '!/^$/' 
```

* "START"と"END"に挟まれた行を表示

```bash
$ awk '/^START$/,/^END$/' 

# 以下は例
$ cat test8.txt # テストデータ
hogehoge1
START
foo3
bar4
hogehoge5

bar7
END
foo9
$ awk '/^START$/,/^END$/' test8.txt
START
foo3
bar4
hogehoge5

bar7
END
```

* "START"と"END"に挟まれた行以外を表示

```bash
$ awk '/^START$/,/^END$/ {next} {print}'
```

* 2行目から4行目だけを表示

```bash
$ awk 'NR==2,NR==4' 
$ awk 'NR>=2 && NR<=4' 
```

* 3列目が"hogehoge"にマッチする行のみ表示

```bash
$ awk '$3 ~ /hogehoge/' 
```

* 3列目が"hogehoge"に一致する行のみ表示

```bash
$ awk '$3 == "hogehoge"' 
```

* ファイルの末尾から4行を表示(tailやheadは使わずに)

```bash
$ awk '{buf[i]=$0; i=(i+1)%4;} END{for(j=0;j<4;j++) print buf[(j+i)%4];}' 
```

* はじめに"--start--"、終わりに "--end--"と表示

```bash
$ awk 'BEGIN{print "--start--"} {print} END{print "--end--"}' 

# 例)
$ cat test13.txt # テストデータ
math english
10 20
30 40
50 60
70 80
$ awk 'BEGIN{print "--start--"} {print} END{print "--end--"}' test13.txt
--start--
math english
10 20
30 40
50 60
70 80
--end--
```

* 2行目以降の1列目の合計を計算して最後に表示する

```bash
$ awk 'NR>=2 {s+=$1} END{print s}' 

# 例)
$ cat test14.txt # テストデータ 
math english
10 20
30 40
50 60
70 80
$ awk 'NR>=2 {s+=$1} END{print s}' test14.txt
160
```

* 2行目以降の1列目の平均を計算して最後に表示する

```bash
$ awk 'NR>=2 {s+=$1;c++} END{print s/c}' 
```

* 2行目以降の1列目の最大値を計算して最後に表示する

```bash
$ awk 'NR>=2 {if($1>a) a=$1} END{print a}' 
```

* 一行目の各フィールドを配列に入れて表示

```bash
$ awk 'NR==1 {cnt=split($0, a); for(i=1;i<=cnt;i++) {print a[i]}}'

# 例)
$ cat test17.txt # テストデータ
math english
10 20
30 40
50 60
70 80
$ awk 'NR==1 {cnt=split($0, a); for(i=1;i<=cnt;i++) {print a[i]}}' test17.txt
math
english
```

* 空白で区切られた文字列の出現回数を各文字列ごとに表示 (uniqコマンドは使わずに)

```bash
$ awk '{for(i=1;i<=NF;i++) a[$i]++} END{for(i in a) {print i":"a[i]}}' 

# 例)
$ cat test18.txt # テストデータ
apple banana lemon
grape orange cherry peach pear strawberry
orange
$ awk '{for(i=1;i<=NF;i++) a[$i]++} END{for(i in a) {print i":"a[i]}}' test18.txt
orange:2
apple:1
strawberry:1
pear:1
banana:1
grape:1
lemon:1
cherry:1
peach:1
$
```
説明：aは連想配列。

* 各行の6文字目以降を捨てる

```bash
$ awk '{print substr($0, 1, 5)}' 
```

* 各行の最初の10文字を捨てる

```bash
$ awk '{print substr($0, 11)}' 
```

* 行末から10文字を表示

```bash
$ awk '{print substr($0, length($0)-9, 10)}'
```

* 1列目は文字列"id"以降の部分を5文字だけ抜き出し、他の列はそのまま出力する

```bash
awk '{$1 = substr($1, index($1, "id"), 5); print}'

# 例)
$ cat test22.txt # テストデータ
iid001id9 orange a b c
$ awk '{$1 = substr($1, index($1, "id"), 5); print}' test22.txt
id001 orange a b c
```

* 1列目の'-'をすべて'/'に置換する

```bash
$ awk '{gsub("-", "/", $1); print}'
```

* 2列目の最初の'-'を'/'に置換する

```bash
$ awk '{sub("-", "/", $2); print}' 
```
* 3列目の２番目の'-'を'/'に置換する

```bash
$ awk '{$3 = gensub("-", "/", 2, $3); print}' 
```

* 各行の最後から2番目の'-'だけ'/'に置換する

```bash
$ awk '{s=$0; cnt=gsub("-", "/", s); if(cnt>=2) $0 = gensub("-", "/", cnt - 1, $0); print}'
```

* 各行の5文字目だけaに置換する

```bash
$ awk '{print gensub(/./, "a", 5, $0)}'
```
* 各行の末尾から5文字目から3文字をhogehogeに置換する

```bash
$ awk '{print substr($0, 1, length($0)-5) gensub(/^.../, "hogehoge", 1, substr($0, length($0)-4))}'
```

* 2列目のアルファベットをすべて大文字にする

```bash
$ awk '{$2=toupper($2); print}'
```

* "(数値)k" となっているところを"(数値)K" に置換する(後方参照)

```bash
$ awk '{print gensub(/([0-9]+)k/, "\\1" "K", "g", $0)}'

# 例)
$ cat test30.txt # テストデータ
10k 20m 30k ok
$ awk '{print gensub(/([0-9]+)k/, "\\1" "K", "g", $0)}' test30.txt
10K 20m 30K ok
```

# 参考
https://www.gnu.org/software/gawk/manual/gawk.html