第29回激しいシェル芸勉強会

# 雰囲気など
[jus共催 第29回シェル芸勉強会 @さくらインターネットさん - Togetterまとめ](https://togetter.com/li/1125585)
[第29回シェル芸勉強会（午前の部） - YouTube](https://www.youtube.com/watch?v=-0DltBwo_5k)
[第29回シェル芸勉強会（午後の部） - YouTube](https://www.youtube.com/watch?v=GyyKvbrcRyw)
[第29回シェル芸勉強会（LT大会） - YouTube](https://www.youtube.com/watch?v=781cEwIQX-w)
[第29回シェル芸勉強会 大阪サテライト LT - YouTube](https://www.youtube.com/watch?v=27iG0E0Rty0)

# 問題
[【問題のみ】第29回激しいシェル芸勉強会 – 上田ブログ](https://blog.ueda.tech/?p=9906)

# Q1

当日思いついたイキった解答。

```
$ cat kadai1 kadai2 | awk '{a[$1 " " $2]+=$3}END{for(k in a){ print k,a[k]}}' | powershell -c '$input | Sort-Object'
```

模範的な解答。

```
$ join -a1 -a2 kadai{1,2} | awk '{print $1, $2, $3+$5}'
```

# Q2

`sed` の `t` は「直前の置換(s)が成功したらラベルへジャンプするコマンド」です。ラベルを省略すると末尾へジャンプするので、条件分岐（というか `goto`）な使い方ができます。

```
$ cat attend6 | tr "," "\n"| sort | sed 's/$/ 出/' | join -a 1 -a 2 attend - | sed 's/ 出$/出/;t;s/.*/&欠/'
```

# Q3

当時思いついた解答（140字に収まらず）。問題を誤認していたので合格者しか出力されず。

```
$ join attend test | 
    powershell -c '
        $input |
        convertfrom-csv -delim " " -head i,n,a,s | 
        ? { ([regex]"出").Matches($_.a).Count -gt ($_.a.length/2)}
    '
```

帰宅後に考え直した解答。
`awk` の関数は覚え直さないと駄目だなぁと。

```
$ join -a1 -a2 attend test | 
    awk '
        NF==3{
            $4=0
        }
        {
            a=$3;
            b=$3;
            gsub("出","",a);
            gsub("欠","",b);
            $4=length(a)<length(b)?$4:0;
            print
        }
        '
```

# Q4.1

時間内に解答できず。
模範解答を参考にした解答。

```
$ echo -1 4 5 2 42 421 44 311 -9 -11 | 
    xargs -n 1 | 
    sort -n | 
    awk '
        {
            if(length($0)==length(a)){printf " " $0 }
            else{printf "\n" $0}
            a=$0}
    ' | 
    grep -v '^$'
```

# Q4.2

時間内に解答できず。
模範解答(タイムライン)を参考にした解答。`sort -g` の一般的な数値というのが謎。 

```
$ echo -1 4 5 2 42 421 44 311 -9 -11 | 
    xargs -n 1 | 
    sort -g |
    awk '
        {
            if(length($0*1)==length(a*1)){printf " " $0 }
            else{printf "\n" $0}
            a=$0}
    ' | 
    grep -v '^$'
```

# Q5

```
$ # 模範解答見てもちょっと意味分からんのでギブアップ
```

# Q6

当時思いついた解答（140字に収まらず）。
特に改良する点も思いつかず、完成度高いのではないかと。

```
$ seq 100 | 
    factor | 
    awk 'NF==2{print $2}' | 
    join -a1 -a2 - <(cat prime | xargs -n 1 | sed 's/.*/& x/') | 
    sed '/x/!s/.*/@/;s/x//' | 
    tr -d '\n' | 
    tr '@' '\n' | 
    grep -v '^$'
```

# Q7

時間内に解答できず。
情報量に圧倒されてしまったのですが、実体参照は２種類しかなかったので落ち着いて考えたら簡単でした。
圧倒されてもとりあえず手を動かすの、大事だと思います。

```
$ cat nyaan.html | 
    grep '#' | 
    sed 's/<span style="">//;
         s@</span><br />@@;
         s/&#160;/ /g;
         s/&quot;/"/g'
```

# Q8

解答方針はすぐ思いついたのですが、`rs` コマンドがなくて断念(CentOS7)。
帰宅後 Ubuntu に `rs` をインストールしてから実行。

```
$ cat shellgei | 
    sed 's/ /@/g;s/./& /g' | 
    rs -T | 
    grep -v '@  @  @  @  @  @  @  @' | 
    rs -T | 
    sed 's/ //g;s/@/ /g'
```

追記です。`datamash` でやってみました。`datamash` は区切り文字のデフォルトがタブなので、`sed` でタブ区切りにしてやる必要があります。

```
$ cat shellgei | 
    sed -r 's/ /@/g; s/./&\t/g' | 
    datamash transpose | 
    sed -r '/^[\t@]+$/d' | 
    datamash transpose | 
    sed -r 's/\t//g;s/@/ /g'
```

# 感想など

午前の部は `perl` でしたが、まぁ黒魔術でした（失礼）。特殊変数と起動オプションについては全然覚えきれていないので[スライド](https://umidori.github.io/shellgei-29th-am/index.html)を再確認しておきます。

午後の部では `rs` が便利なので次回は RHEL 系でも使えるようにしておきます。シェルは基本的に行指向なので `rs -T` で転置できると、対処が簡単になる場合があることが分かりました(Q8)。

`datamash` というコマンドも見慣れなかったものの `rs` と同じようなことができるようなので要調査でした。軽くググってみたところ GNU のプロジェクトがあるみたいなので、機能性については信頼できそうです。

今回の勉強会のテーマになっていた `join` は、これまであまり使う機会が無かったので今回は大変勉強になりました。`join` はコマンドのプロセス置換と合わせて使うことが多く、場合によっては中間ファイルを作った方が見やすくなるように思いました。仕事で使うことがあればよく検討しようと思います。

LT については**大変興味深い**内容ばかりで、ここに感想を ~~書けな~~ 書くよりも動画を直接見て頂きたい気持ちでいっぱいです。