日々之迷歩

世の中わからんことだらけ

ITが複雑で難しくなっていく様に翻弄される日々です。微力ながら共著させていただいた「シェル・ワンライナー160本ノック」をよろしくお願い申し上げまする。

第28回シェル芸勉強会へ遠隔参加

期間限定ではあるが忙しさがピークに達し自分を見失いかけていたため、福岡サテライト会場開催の決断と通知が遅くなってしまい申し訳ない。今回も株式会社エスコ様(旧ベータソフト様)の会議室を利用させていただいた。

会場の担当をしていただいている方は当日業務だったのだが、会場の準備や後片付け、鍵の開け閉めをしていただいた。いつも大変ありがたい。今回は6人の参加者が集った。

イベント関連ページ

本家東京会場募集

usptomo.doorkeeper.jp

大阪サテライト会場募集

atnd.org

福岡サテライト会場募集

atnd.org

大阪サテライト会場レポート

www.kunst1080.net

Togetterまとめ

togetter.com

午前の部

今泉さんによるシグナルの話題だった。福岡の参加者にシグナルについて聞いてみたところ、あまりよく知らないとのことだった。ということで、途中から私なりのシグナルの解説に切り替えてみた。下記のような話題について話をした。

  • プロセスはOSがPIDで管理
  • シグナルでプロセス制御
    • プロセス終了
    • 一時停止
    • コアダンプ
    • 強制終了
    • パイプクローズ
    • ユーザー定義シグナル
  • killコマンドで指定したPIDにシグナル通知
  • Ctrl-CやCtrl-Zなどのキー操作でシグナル通知
  • kill -lでシグナル一覧
  • SIGHUPで設定ファイル再読み込みや再起動(sshdやApache HTTPd Serverなど)
  • seq 100000 | head でSIGPIPEの事例
  • bashのPIPESTATUS

今泉さんの資料はこちら。改めて勉強させていただこう。

www.slideshare.net

休憩している時に、CSVデータを行列置換とかがやりたいけど何か方法は無いか?という話題が上がった。awkなどで頑張る方法もあるが、とりあえずrsコマンドについて紹介した。-Tオプションで行列入替えが出来る。

$ seq 10 | xargs -n 2
1 2
3 4
5 6
7 8
9 10

$ seq 10 | xargs -n 2 | rs -T
1   3   5   7   9
2   4   6   8   10

ちなみに同様な処理をするのに、Tukubaiのtateyokoというコマンドがある。こちらは区切りの空白が1つだけなので使いやすい。

Tukubaiオンラインコマンドマニュアル: tateyoko(1)

内容としては、CSVデータをRDBに入れてJOINしたりするためのデータということだった。最近テキストファイルをキーで連結する処理をやった事例があり、TLで話してみようかと準備をしていた。そこで午前中ではあるが資料の話をすることにした。

speakerdeck.com

昼食

お昼は会場近くの餃子の王将。定番になりつつある。Software Designの2017年1月号を購入してシェル芸特集を読んでやってみたという方がいらっしゃって良かった、大変良かった。

午後の部

いよいよ実践で悶える時間の始まり。今回もsedがメインのようだが、awkの力も借りつつLaTeXの文章を弄くり回す地獄を味わえということだった。問題と解答は下記リンクを参照のこと。難易度は比較的高めかも。

【問題と解答】第28回基準値を超えるシェル芸勉強会 – 上田ブログ

福岡サテライトで考えて解説した内容は下記の通り。今回は気分を変えてUbuntuで解いた。

Q1.1

会長の解答通り

Q1.2

上田会長の現地での解答例を参考にして解説。まずはsedgrep-Bオプションで必要になりそうな行を抜き出す。

$ cat contents.tex | sed -n '/\\begin{figure}/,/\\end{figure}/p' | grep -B1 caption
        \includegraphics[width=0.5\linewidth]{./figs/coordinate.eps}
        \caption{世界座標系とロボットの姿勢}
--
        \includegraphics[width=0.5\linewidth]{./figs/observation.eps}
        \caption{計測値}
--
        \includegraphics[width=0.5\linewidth]{./figs/two_poses.eps}
        \caption{ランドマークの計測値から2点の相対姿勢を求める}
--
        \includegraphics[width=0.8\linewidth]{./figs/observation_noise.eps}
        \caption{ランドマークの計測値の不確かさを表す共分散行列}

次に{}の前後を消し去る。

$ cat contents.tex | sed -n '/\\begin{figure}/,/\\end{figure}/p' | grep -B1 caption | sed 's/^.*{//' | sed 's/}.*$//'
./figs/coordinate.eps
世界座標系とロボットの姿勢
--
./figs/observation.eps
計測値
--
./figs/two_poses.eps
ランドマークの計測値から2点の相対姿勢を求める
--
./figs/observation_noise.eps
ランドマークの計測値の不確かさを表す共分散行列

後は並べ替えして整理すれば完成。

$ cat contents.tex | sed -n '/\\begin{figure}/,/\\end{figure}/p' | grep -B1 caption | sed 's/^.*{//' | sed 's/}.*$//' | xargs -n 3 | awk '{print $2,$1}'
世界座標系とロボットの姿勢 ./figs/coordinate.eps
計測値 ./figs/observation.eps
ランドマークの計測値から2点の相対姿勢を求める ./figs/two_poses.eps
ランドマークの計測値の不確かさを表す共分散行列 ./figs/observation_noise.eps

Q2

上田会長の解答例を参考にした。内容が複雑で追いつく余裕が無かったため、段落番号を付けて2章だけ抜き出す処理を理解してもらった。

$ cat contents.tex | awk '/\\section/{a+=1}{print a,$0}' | grep '^2'
2 \section{問題}
2 
2 %対向二輪型(その場で回転できるロボット)で、
2 平面上を移動し、向きを持ち、カメラでランドマーク観測ができるロボットで
...
2 任意のロボットの軌跡$\V{x}_{0:T}$がどれだけ$Z_{0:T}$を説明するかを
2 評価関数として定式化し、この評価関数を用いた最適化問題として定義する。
2 この評価関数については、次章の実装の中で説明する。

Q3

詳しく追う余裕がなかったため、一旦一行にしてしまってから、キーワードの前後に改行を入れると扱いやすくなる、という技を解説するに留めておいた。

$ cat contents.tex | tr -d '\n' | sed 's/\\footnote{/\n&\n/g' 

Q4

キーを元にして、awkでデータをファイル別に分割する事例だ。参加者の方々はこの技を知らないみたいだったため、問題を離れて下記の例を解説した。

数値を10で割った余り毎にデータを分割。

$ seq 100 | awk '{a=$1%10; print $1 > "file"a}'
$ head -n 2 file*
==> file0 <==
10
20

==> file1 <==
1
11

...

==> file8 <==
8
18

==> file9 <==
9
19

Apacheログファイルを接続元ホスト毎に分割

$ head -n 3 access_log
192.168.0.1 - - [01/Jul/1995:00:00:01 +0900] "GET /history/apollo/ HTTP/1.0" 200 6245
192.168.0.2 - - [01/Jul/1995:00:00:06 +0900] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
192.168.0.3 - - [01/Jul/1995:00:00:09 +0900] "GET /shuttle/missions/sts-73/mission-sts-73.html HTTP/1.0" 200 4085

$ mkdir sources

$ cat access_log | awk '{print $0 > "sources/"$1}'

$ head -n 1 sources/*
==> sources/192.168.0.1 <==
192.168.0.1 - - [01/Jul/1995:00:00:01 +0900] "GET /history/apollo/ HTTP/1.0" 200 6245

==> sources/192.168.0.2 <==
192.168.0.2 - - [01/Jul/1995:00:00:06 +0900] "GET /shuttle/countdown/ HTTP/1.0" 200 3985
...

Q5

上田会長の解説を参考にして解説。「わかち書き」が出来るmecabについて説明した。

Q6

上田会長の解説を参考にして解説。

Q7

余裕が無かったので出来なかった。

Q8

上田会長の解説を参考にしたが、思ったような出力にならない不完全解答になっちゃった。

$ cat contents.tex | grep 'section' | grep -v '^%' | sed 's/\\label{.*}$//' | sed 's/{/ /' | sed 's/}$/ /' | awk '/\\sec/{s+=1;ss=0}/\\subsection/{ss+=1;sss=0}/\\subsubsection/{sss+=1}{print s"."ss"."sss,$0}'
1.0. \section はじめに 
2.0. \section 問題 
2.1.0 \subsection ロボットの姿勢と座標系 
2.2.0 \subsection 観測 
2.2.1 \subsubsection ランドマークの識別 
2.2.2 \subsubsection ランドマークの姿勢計測 
2.2.3 \subsubsection 計測値の記録 
2.2.4 \subsubsection 計測値の誤差 
2.3.0 \subsection 完全SLAM問題 
3.0.0 \section graph-based SLAMの実装例 
3.1.0 \subsection グラフのエッジを作る 
3.1.1 \subsubsection $\V{\mu}_{c,t,t'}, \V{e}_{c,t,t'}$の計算 
3.1.2 \subsubsection $\Sigma_{c,t,t'}, \Omega_{c,t,t'}$の計算 
3.2.0 \subsection 最適化問題を作る 
3.2.1 \subsubsection マハラノビス距離 
3.2.2 \subsubsection 最適化する式 
3.3.0 \subsection $\V{e}_{c,t,t'}$の勾配を求める 
3.4.0 \subsection 問題を解く 

午後の部終了後

順番が前後したが、イントロとして準備しておいた資料の話をした。

speakerdeck.com

九九の答えが36種類

数学的な証明については、大阪サテライト担当の@kunst1080さんが頑張っておられるので参照して欲しい。

www.kunst1080.net

九九の答えが36種類であることについて、Ruby芸でmapとreduceを使って確認してみた。考え方は@ebanさんの下記のシェル芸とほぼ同じ。

Rubyのrepeated_combinationと、mapとreduceでやってみる。

$ irb
irb(main):001:0> (1..9).to_a.repeated_combination(2).map{|a|a.reduce(:*)}.uniq.size
=> 36

そもそもreduce要らんかった。まあ3個以上の掛け算だったらreduce使えばええか。

irb(main):001:0> (1..9).to_a.repeated_combination(2).map{|a,b|a*b}.uniq.size
=> 36

次に計算結果を素因数分解して、掛け算のパターンを数えてみる。シェル芸もRuby芸も考え方の流れは同じ。

まずはシェル芸で。1列目をTukubaiのdelfコマンドを使っている。awkなどで消しても可。

$ echo {1..9}\*{1..9}\; | bc | factor | delf 1 | sort | uniq

2
2 2
2 2 2
2 2 2 2
2 2 2 2 2
2 2 2 2 2 2
2 2 2 2 3
2 2 2 3
2 2 2 3 3
2 2 2 5
2 2 2 7
2 2 3
2 2 3 3
2 2 5
2 2 7
2 3
2 3 3
2 3 3 3
2 3 5
2 3 7
2 5
2 7
3
3 3
3 3 3
3 3 3 3
3 3 5
3 3 7
3 5
3 7
5
5 5
5 7
7
7 7

$ echo {1..9}\*{1..9}\; | bc | factor | delf 1 | sort | uniq | wc -l
      36

次にRuby芸で。irbを利用。

$ irb -r 'prime'
irb(main):001:0> (1..9).to_a.repeated_combination(2).map{|a,b|a*b}.map{|a|Prime.prime_division(a).map{|p,n|[p]*n}.flatten}.uniq
=> [[], [2], [3], [2, 2], [5], [2, 3], [7], [2, 2, 2], [3, 3], [2, 5], [2, 2, 3], [2, 7], [2, 2, 2, 2], [2, 3, 3], [3, 5], [3, 7], [2, 2, 2, 3], [3, 3, 3], [2, 2, 5], [2, 2, 7], [2, 2, 2, 2, 2], [2, 2, 3, 3], [5, 5], [2, 3, 5], [5, 7], [2, 2, 2, 5], [3, 3, 5], [2, 3, 7], [2, 2, 2, 2, 3], [2, 3, 3, 3], [7, 7], [2, 2, 2, 7], [3, 3, 7], [2, 2, 2, 2, 2, 2], [2, 2, 2, 3, 3], [3, 3, 3, 3]]
irb(main):002:0> 
(1..9).to_a.repeated_combination(2).map{|a,b|a*b}.map{|a|Prime.prime_division(a).map{|p,n|[p]*n}.flatten}.uniq.size
=> 36

ASCIIコード問題

競プロな方のTwitter LTで、ASCIIコードの大小を確認する話題があった。@ebanさんからLANG=Cな条件だとsortコマンドはASCIIコード順に並べ替えしてくれるというアドバイスをいただいた件を話した。

それからASCIIコード順に文字列を列挙する方法として、下記のような例を話した。

awkを使う

$ seq 33 125 | awk '{printf "%d %c\n",$1,$1}'
33 !
34 "
35 #
...
123 {
124 |
125 }

iprintを使う(MacやUbuntuならパッケージでインストール可)

$ seq 33 125 | xargs i
33 0x21 041 0b100001 '!'
34 0x22 042 0b100010 '"'
35 0x23 043 0b100011 '#'
...
123 0x7B 0173 0b1111011 '{'
124 0x7C 0174 0b1111100 '|'
125 0x7D 0175 0b1111101 '}'

man asciiでasciiコードのマニュアルを開く

ASCII(7)             BSD Miscellaneous Information Manual             ASCII(7)

NAME
     ascii -- octal, hexadecimal and decimal ASCII character sets

DESCRIPTION
     The octal set:

     000 nul  001 soh  002 stx  003 etx  004 eot  005 enq  006 ack  007 bel
     010 bs   011 ht   012 nl   013 vt   014 np   015 cr   016 so   017 si
     020 dle  021 dc1  022 dc2  023 dc3  024 dc4  025 nak  026 syn  027 etb
     030 can  031 em   032 sub  033 esc  034 fs   035 gs   036 rs   037 us
     040 sp   041  !   042  "   043  #   044  $   045  %   046  &   047  '
     050  (   051  )   052  *   053  +   054  ,   055  -   056  .   057  /
     060  0   061  1   062  2   063  3   064  4   065  5   066  6   067  7
     070  8   071  9   072  :   073  ;   074  <   075  =   076  >   077  ?
     100  @   101  A   102  B   103  C   104  D   105  E   106  F   107  G
     110  H   111  I   112  J   113  K   114  L   115  M   116  N   117  O
     120  P   121  Q   122  R   123  S   124  T   125  U   126  V   127  W
     130  X   131  Y   132  Z   133  [   134  \   135  ]   136  ^   137  _
     140  `   141  a   142  b   143  c   144  d   145  e   146  f   147  g
     150  h   151  i   152  j   153  k   154  l   155  m   156  n   157  o
     160  p   161  q   162  r   163  s   164  t   165  u   166  v   167  w
     170  x   171  y   172  z   173  {   174  |   175  }   176  ~   177 del

実は先日の夜の飲み会で結構飲んでおり、酔っ払いの翌日で若干体調が不良だったという・・・まあなんとか乗り切った?その飲み会の時に誘った方も来ていただいた。UNIXはあまり触ったことがないということで、出来るだけサポートはさせていただいたつもりだがどうだっただろうか?

今回も自分なりに解説やサポート、話題提供を頑張ったつもりである。福岡サテライト会場、東京と大阪の会場の皆様方、お疲れ様である。