読者です 読者をやめる 読者になる 読者になる

日々之迷歩

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

ITが複雑で難しくなっていく様に翻弄される日々です

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

Shell Tukubai シェル芸

寒い!おまけに年の瀬!!であるにも関わらず、ご参加いただきありがたやありがたや。また素晴らしい会場のご提供もありがたやありがたや。そしてまた写真撮るの忘れた・・・

第20回シェル芸勉強会の福岡サテライト会場を開設させていただいた。イベント案内はこちら。

atnd.org

東京の本家勉強会案内はこちら。

usptomo.doorkeeper.jp

今回は午前中が初心者向け内容で、午後からが本番!?という感じの流れだった。午前中からUstreamによる参加で予定していたが、最初の流れに乗りそこなったため、斎藤さんが事前に配布されていた資料のPDFを使ってawk勉強会を開いた。,で範囲指定とか、後半は実は知らなかったことが結構あって、勉強になったでござる。アクションを使わずにパターンだけで処理するのが混乱新鮮だった。資料とサンプルデータはこちら。

awk勉強会で時間的にも手一杯、後半のシェル変数展開に関する話題は出来なかった。

昼食は近くの餃子王将に皆さんでお出かけ。お仕事どんなことしてるのかとか、最近のsamba事情!?とか色々お話が出来た。samba・・・そう言えば最近最新の状況とか追いかけてなかったな。

帰ってきてからは、皆さんの環境作成とかをしたりした。今回はMacDebianFreeBSDなど環境が色々だった。X Window環境なしのFreeBSDで、コンソールに直接ログインされていたが、日本語の扱いに問題ありだった。TeraTermsshログインしてくれとか、事前のアナウンスが必要かもしれないと思った。

その後午後の部突入。いよいよ本番。今回もなかなか手強いぞ・・・ギブアップな問題があったり、そもそも問題の意味を取り違えたりしていたのもあり。問題を解くというよりは、参加者の方の理解をサポートすることを重視した。自分なりに頑張ってみた。が、伝わったかなあ???

今回の問題と解答はこちら。

【問題と解答】第20回記念、年末年始の浮ついた気分大粉砕シェル芸勉強会 – 上田ブログ

以下、各問題について私なりの解答と、参加者の方への説明について。

Q1

ウォーミングアップ的な問題か。福岡サテライトは初心者の方が多いので、先に私が解いた後、解き方と考え方の説明を行った。私なりの解答例はこちら。

$ grep '' * | tr ':' ' ' | self 1.1.6 2 | sort -k1,1 -k2,2n |
 getlast 1 1
$ grep '' * | tr ':' ' ' |
 awk '{if(a[substr($1,1,6)]<$2){a[substr($1,1,6)]=$2}}END{for(v in a){print v,a[v]}}'

まずgrep '' *で、ファイル名とファイルの内容を表示するというところを説明。

$ grep '' *
file_A-1:1
file_A-1:31351
....
file_B-2:9912
file_B-2:4488

そこから後は、ファイル名をfile_Aとfile_Bの部分を切り出し、

$ grep '' * | tr ':' ' ' | self 1.1.6 2
file_A 1
file_A 31351
....
file_B 9912
file_B 4488

並べ替えてTukubaiのgetlastで最後を表示。

$ grep '' * | tr ':' ' ' | self 1.1.6 2 | sort -k1,1 -k2,2n |
 getlast 1 1
file_A 233333
file_B 9912

もう一つの解答はawk芸。連想配列を使ってより大きい値で置き換えていく、という説明をした。

Q2

要するにスクレイピングの問題。これも先に私が解いてから説明を行った。

$ curl http://ja.uncyclopedia.info/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8 |
> sed -n '/<pre>/,/<\/pre>/p' | sed -n '12p' | sed 's/^$ //' | sh

sedの説明にちょうど良い問題となった。sedで必要な部分を切り出していけば良い。UNIXではシェルもコマンドの一つに過ぎないので、コマンド文字列をパイプで流し込むことで実行出来ることを補足した。

Q3

これは完全に問題の意図を読み間違えていた。奇数行と偶数行を分割すると思い込んでいた・・・

ということで、奇数行を1列目、偶数行を2列目に分ける方法を下記のように解説した。xargsについては、のちに本来の使い方を説明した。

$ seq 1 4 | awk 'NR%2==0{print}NR%2{printf $0" "}'
1 2
3 4

$ seq 1 4 | xargs -n2
1 2
3 4    

$ cat Q3 | yarr -2
1 2
3 4

Q4

こ、これわ・・・とりあえず下記のような回答でお茶を濁して・・・(一応動いた)

$ ps x | grep grep | self 2 | ggrep -vf - <(ps x | grep bash) |
 self 1 | xargs kill

これについては、前半でkillするプロセスIDのリストを作ってxargs killに渡すという流れを説明。あまり時間が取れなかったので、考え方を聞いてもらって詳しいことは割愛した。xargsについては、重要性と使い方を補足した。

追記

本家解答例がLinux版なので、Mac版に改造。

$ a=$(tty | sed 's;/dev/tty;;') ; ps aux | awk '$7~/s[0-9]*/' |
 awk -v "t=$a" '$7!=t' | awk '{print $2}' | xargs kill

Q5

ギ、ギブ・・・ということで、素因数分解が出来るfactorコマンドの紹介と説明、素数列挙方法の説明をした。

$ seq 10 | gfactor
1:
2: 2
3: 3
....
8: 2 2 2
9: 3 3
10: 2 5

素数の場合はフィールド数が2、なのでawkで続いて捌く。

$ seq 10 | gfactor | awk 'NF==2{print $2}'
2
3
5
7

Q6

Tukubai便利ちゃんなので・・・Tukubai芸で解いた。

$ cat Q6 | tr ' ' ' ' | juni | tarr num=1 | juni 1 1 | self 3 1 |
 sort -k1,1 | yarr num=1

まずは行番号をつけてデータを縦に並べる。まずはこの発想が必要かも?

$ cat Q6 | tr ' ' ' ' | juni | tarr num=1
1 山田
1 上田
1 吉田
1 武田
2 吉田
2 武田
2 上田
2 山田

そしてTukubaiのjuniコマンドの本来の使い方、キーが同じ範囲でカウントアップする。これで、列番号、行番号、データの順番で表示が出来る。

$ cat Q6 | tr ' ' ' ' | juni | tarr num=1 | juni 1 1
1 1 山田
2 1 上田
3 1 吉田
4 1 武田
1 2 吉田
2 2 武田
3 2 上田
4 2 山田

ここまでくれば、列番号とデータだけを抜き出し、適宜並べ替え処理。yarrで列番号を横に並べて完成。

$ cat Q6 | tr ' ' ' ' | juni | tarr num=1 | juni 1 1 | self 3 1 |
 sort -k1,1 | yarr num=1
上田 2 3
吉田 1 3
山田 1 4
武田 2 4

Q7

ギ、ギブ・・・・ということで会長の回答について説明をした。

それから余談で、bcコマンドの使い方について説明をした。16進数で表示するやり方はこんな感じ。

$ bc
bc 1.06
Copyright 1991-1994, 1997, 1998, 2000 Free Software Foundation, Inc.
This is free software with ABSOLUTELY NO WARRANTY.
For details type `warranty'. 
obase=16 <=入力
10
A <= 入力
100
64 <= 入力
quit

10進数で1から100までを16進数で表示するにはこちら、という解説をした。

$ seq 16 | ( echo obase=16; cat ) | bc
1
2
3
4
5
6
7
8
9
A
B
C
D
E
F
10

Q8

ギ、ギブ・・・

ということで、とりあえず下記のようにtrコマンドとsedコマンドの同様な使い方について説明した。

$ cat Q8 | tr '一二三四五六七八九' '123456789'
5千7百3十5
4千3
4十5
9万6千2百3十3
十1
百十2

$ cat Q8 | sed 'y/一二三四五六七八九/123456789/'
5千7百3十5
4千3
4十5
9万6千2百3十3
十1
百十2

最後にxargsの使い方など補足の説明を行って完了となった。やはり内容の多さに対して時間が短い・・・という悩み。

こういうUNIXのコマンドやシェルを使った操作などはどうやって勉強したりすれば良いのか?という質問があった。実践的に手を動かすための機会や題材が無い、という印象だった。今回はシェル芸本2冊やUECのWebサイトを紹介したが、やはり自分だけでやるには余程モチベーションが無いと難しいかもしれないなと。初心者向けシェル芸勉強会をどう展開していくか?を考えることにもつながりそうだ。

さて、本家の解答例をこれから見てお勉強してみようかしら・・・