しました
午前
構造化プログラミング入門の2回目でした。ジャクソン流構造化プログラミングについての講義で、例題に図を描いてみたりなどをしました。
配信はこちら
午後
今回はPowerShellでも解きます。問題と解答はこちら
Q1
1行目に今日の日付、3行目以降にN日後の予定が書かれているファイルがあります。このN日後を具体的な日付になおしてくださいという問題。
$ cat She*/vol.58/memo | sed 's/日後/ days@/' | awk 'NR==1{d=$2}NR>2{$1=d;print}' | sed 'y/年月日/-- /' | teip -f1 -d@ -- zsh -c "while read L;do date -d \$L +'* %Y年%m月%d日';done" | tr -d @ * 2022年03月07日: ワクチン接種 * 2022年03月11日: 国際ロボット展 * 2022年03月12日: シェル芸勉強会
N日後の部分を、2022-03-05 n days
に変換、teip
で日付のフィールドだけ選択して date
に渡し、日付を計算させる感じです。
PowerShellでもやってみます。
$ DATE=iex 'cat .\memo |%{"$_" -split " "} | select -Index 1' $ cat .\memo | select -Skip 2 | %{ $x="$_" -split " "; $x[1]=(date $DATE).AddDays(+($x[1] -replace "日後:","")).ToString("yyyy年MM月dd日:");$x -join " " }
Get-Date
で日付のオブジェクトが得られ、そこに生えてるAddDays
で日付を計算して出力しています。
.NETを少し触るので System.Hoge
に生えてる!みたいなのはちょっとわかるんですけどPowerShell独特の書き方がまだわからんですね。
Q2
数字を使わずに date
コマンドに 2022年02月22日 2 22:22:22 を出力させる問題。日付と時間の間にあるのは、火曜日を表す2とのこと
false;a=$?;true;b=$?;date --date "$(date +%Y)-$b$((a+a))-$((a+a))$((a+a)) $((a+a))$((a+a)):$((a+a))$((a+a)):$((a+a))$((a+a))" +"%Y年%m月%d日 %u %T"
無理やり。数値を終了コードから持ってきて計算を繰り返すという感じです。
$ Get-Date (Get-Date).AddMonths(-1).AddDays(7) -UFormat "%Y年%m月%d日 %u %d:%d:%d" 2022年02月22日 2 22:22:22
PowerShellの方ではtwitterに投稿された賢い方法でやりました。2022年3月15日に書いてるので、足したり引いたりする部分は当日とは違いますが
Q3
$ cat 13.json | gron | grep line_ | sel -gd "\.|=" -D: 3 4 | sed 's/ :/:/' | tr -d \; | sed 's/line_cd/ - &/;s/line_name/ &/;1iline:' | head
yq
を使えば一撃なんですが、それなしで解いてみました。必要なところ切り出して~インデントつけて~って少々面倒になっちゃいますね。やはり決まったデータ構造の変換は専用のツールに任せるのが楽ですね
$ cat .\13.json | ConvertFrom-Json | ConvertTo-Yaml
PowerShellにはpowershell-yaml
というモジュールがあり、変換をえいでやってくれるので楽です。
Q4
尺取り虫みたいな動きをするうんこの動画を作る問題。しゃくとりうんこというらしい…うむ…
$ yes $(echo 💩{,,,,,,,,,}| tr -d ' ') | awk -F '' '{$(NR%10?NR%10:10)="@";print}' OFS='' | rev | awk '{for(i=0;i<NR/10;i++)printf " ";print}' | tr @ ' ' | head -n 300 | textimg -a
このワンライナーのうち、textimgの部分を外すと
💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩 💩💩💩 💩💩💩💩💩 💩💩💩💩 💩💩💩💩 💩💩💩💩💩 💩💩💩 💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩 💩💩💩 💩💩💩💩💩 💩💩💩💩 💩💩💩💩 💩💩💩💩💩 💩💩💩 💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩 💩💩💩 💩💩💩💩💩 💩💩💩💩 💩💩💩💩 💩💩💩💩💩 💩💩💩 💩💩💩💩💩💩 💩💩 💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩💩 💩💩💩💩💩💩💩💩 💩 💩💩💩💩💩💩💩 💩💩 ...
10行ごとにインデントが深くなるしゃくとりうんこが出力されます。2つのawk
でできていて、前半はしゃくとり動作、後半はインデントを頭につけるものですね
$ $NR=0;[System.Linq.Enumerable]::Repeat([System.Linq.Enumerable]::Repeat('💩', 10) -join " ",30) |%{$x="$_" -split " ";$x[$NR%10]=" ";[array]::Reverse($x);" "*[Math]::Floor(($NR/10))+($x -join "");$NR++}
PowerShellでも同様の指針です。$NR/10
が四捨五入されるというのにハマってしまったのでPowerShellむずい…ってなりました
Q5
危険シェル芸なのでスキップ
Q6
file1
、file2
から似た文字列のペアを作る問題。
join -j9 She*/vol.58/file* | while read L R; do echo $L $R $(echo $L | grep -o . | sort | diff - <(echo $R | grep -o . | sort) | wc -l); done | sort -nk3 | head -n4 | sel 1 2
方針としてはなんちゃって編集距離を計算して、距離が近いもの同士をペアにするというものです。単語を分解してソート、diff
を取って出力行数を編集距離とし、出力します。これをすべてのペアで行い、小さい順に取り出すという感じです。
$ cat .\file1 | Join-Object -RightObject (cat .\file2) -JoinType Cross |%{ @{x=$_;c=(diff ($_[0] -split "" | sort) ($_[1] -split "" | sort)).Count} } | Sort-Object -Property c | select -First 4 |%{$_.x -join " "}
PowerShellでも同じ方針にしてみました。Join-ObjectはJoinModuleで入手できます。
Q7
めちゃデカファイル nums.gz
には数値がたくさん書いてあるので、その合計を計算する問題。
$ (zgrep '[0-9]' nums.gz ;zgrep -v '[0-9]' nums.gz | numconv) | awk '{s+=$1}END{print s}'
時間中に解けなかったので解説通りの解で。zgrep
に与える正規表現を^[0-9]*$
にしたら一生終わらなかったので最小にしてみました。処理時間が話題になっていたので自分でも測ってみると
11.78s user 1.30s system 80% cpu 16.251 total
でした。PowerShellのほうはzcat
相当のことをやるのがめんどくさかったのでやめときました
LT
今回もLTさせていただきました!
今回はsurge
というコマンドを作りましたという話をしました。「行を列に変換し、任意のコマンドのSTDINへ流し込み、その出力を行に戻して出力する」というものです。while read L; do ... done
のショートハンド的なコマンドですね。while read L;do ... done
だとパフォーマンスが残念なこと、コマンドを適用したいだけなのにそれ以外の部分の分量が多くてつらいことが気になっていたので作ってみました。
そのうち個別の記事でも書きたいと思っています。
ちなみに surge
を使って以下のように書けば
$ (zgrep '[0-9]' nums.gz ;zgrep -v '[0-9]' nums.gz | numconv) | paste -{,,,,,} | surge -P 20 -- awk '{s+=$1}END{print s}' | awk '{s+=$1}END{print s}'
Q7を並列で計算させることもできるんですが、むしろ遅くなるので適材適所って感じがしますね。
おわり
今回もとても楽しかったです!次回は自分の気になる話があるのとことだったので今から楽しみです。企画・開催ありがとうございました!