今日は初心者向け「第25回シェル芸勉強会 大阪サテライト」の記録

はじめに

10月29日(土)に開催された「第25回シェル芸勉強会 大阪サテライト」に参加しました。

今回は従来より開始時間が15分早くなりましたが、朝9時45分から夜18時まで従来通りsh行三昧の一日でした。

メイン会場および他サテライト会場

各会場の様子

問題ならびに模範解答

ライブストリーム(YouTube)


午前の部: シェルに関する勉強会

  • man grep
    • 講師: Ryuichi Ueda(@ryuichiueda)さん
      • grepとは
      • 兄弟プログラムegrepfgrep
      • 様々なオプション
        • -E: 拡張正規表現
        • -F: パターンを固定文字列として扱う
        • -P: Perl正規表現
        • -e: 複数パターン指定
        • -f: パターンをファイルから読み込む
        • -i: 大文字と小文字の区別を無視
        • -v: マッチしない行を表示
        • -w: 完全な単語とマッチした場合は表示
        • -x: 行全体とマッチした場合は表示
        • -c: マッチした行数を表示
        • --color: 色付きで表示
        • -L: マッチしないファイル名を表示
        • -l: マッチするファイル名を表示
        • -m NUM: マッチ行数がNUMに達したら中止
        • -o: マッチした部分ごとに改行して表示
        • -q: 何も出力せず、マッチの成否を終了ステータスにする
        • (…以下略…)

午後の部: シェル芸勉強会

  • いずれの問題も、Debian 8「jessie」の32ビットPC版で解答しています。
  • 使用OSによっては、sortを実行する言語環境をLANG=Cにする必要があるかも知れません。

Q1: IPアドレスだけ出力

$ ping -c1 www.usptomo.com | head -n1 | sed -r 's/^[^(]*//;s/\).*//;s/\(//'
157.7.203.188

pingした結果からsedで不要な部分を削除します。

Q2: すべての循環パターンを生成

$ echo ひらけ!ポンキッキ | sed -r ':;p;s/^(.)(.*)/\2\1/;b' | head -n9
ひらけ!ポンキッキ
らけ!ポンキッキひ
け!ポンキッキひら
!ポンキッキひらけ
ポンキッキひらけ!
ンキッキひらけ!ポ
キッキひらけ!ポン
ッキひらけ!ポンキ
キひらけ!ポンキッ

sedで文字列を1文字ずつ移動させる無限ループを実行し、head -n9で最初の9行だけ出力します。

Q3: 制限付きシェル下でのファイル書込

$ rbash
[mitsuhisa@debian 第25回シェル芸勉強会]$ : > hoge
rbash: hoge: 制限されています: 出力をリダイレクト出来ません
$ grep '/bash$' /etc/passwd | sed 'w hoge'
root:x:0:0:root:/root:/bin/bash
mitsuhisa:x:1000:1000:KUSANAGI Mitsuhisa,,,:/home/mitsuhisa:/bin/bash
$ cat hoge
root:x:0:0:root:/root:/bin/bash
mitsuhisa:x:1000:1000:KUSANAGI Mitsuhisa,,,:/home/mitsuhisa:/bin/bash

bashをrbashの名前で起動すると、

  • リダイレクトが使えなくなる
  • bashの環境変数の値を変更できなくなる

など、シェルには様々な制限がかかりますが、

sedwコマンド

w filename
    現在のパターンスペースを filename に書き込む。

でファイルに書き込むことができます。

Q4: 濁点がつく字だけに濁点をつける

当日に解答できなかった問題です。

$ echo すけふぇにんけん | nkf --katakana | nkf -Z4 | sed 's/./&゙/g' | nkf --hiragana | sed 's/゛//g'
ずげぶぇにんげん

文字の変換には一般的にnkfを使いますが、この問題を解くために次のオプションを使っています。

  • --katakana: 片仮名に変換
  • --hiragana: 平仮名に変換
  • -Z4: 全角カナから半角カナに変換

濁点の処理はsedで行っています。

Q5: アニメーション

訂正: 当日の解答は誤った解答であるため、次のようなワンライナーに訂正します。

$ while :; do echo -n '*'; sleep 1; done
**********^C

while :でループを1回実行するごとに「*」が1つずつ増えていく無限ループを実行しています。

なお、ループの末尾ではsleep 1を用いて処理を1秒間停止しています。

Q6: 文字列を復元

当日に解答できなかった問題です。

$ cat crypt
b730a730eb30b8820a00
$ echo -e $(cat crypt | sed -r 's/(..)(..)/\\u\2\1/g')
シェル芸

当日は、最後の「0a00」が改行文字(0x0a)とヌル文字(0x00)だと思い、そこから悪戦苦闘したところで時間切れとなりました。

実際は、バイトオーダーをリトルエンディアンにしたものということなので、sedで各バイトを入れ替えてecho -eで表示します。

nkfのオプションで、入力コードとしてリトルエンディアンのUTF-16を仮定する-W16Lを用いた

$ cat crypt | xxd -p -r | nkf -W16L
シェル芸

という解法もあります。

Q7: UNIX時刻で素数になるものを世界標準時で表示

$ seq $(date -ud 2016-10-29 +%s) $(date -ud 2016-10-30 +%s) | sed '$d' | factor | awk 'NF==2{print $2}' | xargs -n1 -I% date -ud @%
2016年 10月 29日 土曜日 00:00:07 UTC
2016年 10月 29日 土曜日 00:00:13 UTC
2016年 10月 29日 土曜日 00:00:19 UTC
(...略...)
2016年 10月 29日 土曜日 23:59:17 UTC
2016年 10月 29日 土曜日 23:59:23 UTC
2016年 10月 29日 土曜日 23:59:43 UTC

基本的な解法は、

  1. seq $(date -ud 2016-10-29 +%s) $(date -ud 2016-10-30 +%s) | sed '$d'で、指定された日(2016年10月29日)の範囲に含まれるUNIX時刻を列挙
  2. factor | awk 'NF==2{print $2}'で、素数だけを抽出
  3. xargs -n1 -I% date -ud @%で、人間にとって読みやすい日付文字列にする

という手順になっています。

Q8: サイン波を描く

$ echo 'plot(X=-5,5,sin(X))' | gp -fq | sed '$d;s/^.\{10\}//' | sed "s/[\'\`.|]/ /g;s/[^ ]/*/g"

*****                                  *****
     *                                *     **
      *                              *        *
       *                            *
        *                                      *
                                   *            *
         *                        *
                                                 *
          *                      *                *
           *
                                *                  *
            *                  *
                                                    *
             *                *                      *
              *
                             *                        *
               *            *
                *                                      *
                           *                            *
                 *        *                              *
                  **     *                                *
                    *****                                  *****

計算機代数システムPARI/GPのgpにはプロット機能がありますが、解答に使うには不要な文字が多いのでsedで掃除しています。


LT大会

  1. シェルスクリプトでGnuCashを使いやすく
    • 発表者: 日柳 光久(@mikkun_jp)
      • GnuCashは優れたフリーの会計ソフトだが、請求書のデザインが今ひとつ
      • シェルスクリプトを作って解決
  2. バイナリをbase64してからgzipするとファイルサイズは小さくなるのか??????
    • 発表者: くんすと(@kunst1080)さん
      • gzipについて、テキストは圧縮率が高い
      • バイナリをbase64でテキストにした場合はどうなるか
      • 「hello worldプログラム」のソースおよびバイナリ、そして画像でも検証
      • base64の際に情報量が増えるので、gzipしてもその分だけサイズは増える
      • base64しない方が軽い
  3. アスキーアートワンライナー
    ※延長戦含む
    • 発表者: MSR(@msr386)さん
      • いわゆる「突然の死」をワンライナーで実装
      • slをワンライナーで実装
      • ターミナル画面をワンライナーでぐちゃぐちゃにする(延長戦)
  4. パイプを通るPDF
    ※詳細: パイプを通るPDF(実験中) 〜 #シェル芸 の新たなる境地へ
    • 発表者: T.Motooka(@t_motooka)さん
      • convert xc:none -page A4 pdf:-で中身が空のPDFを生成し、標準出力に送ることができる
      • その後、gsや他のコマンドで何かできないか?
  5. tmuxチートシート
    • 発表者: nmrmsys(@nmrmsys)さん
      • コマンドライン指定(tmux kill-serverでtmux全体を終了、など)
      • キー操作(?でキーバインド一覧、]でコピーした内容を貼り付け、など)
      • 設定エトセトラ(set-option -g mouse onでマウス操作を有効にする、など)

おわりに

午前の部では、CLIでよくお世話になっているgrepのオプションを学び直すことができました。特に、空白や改行文字を含むような行儀の悪いファイル名に対応するための-Zオプションや-zオプションは、これからのシェル芸に役立ちそうです。

午後の部は、パズル的な問題が出され、CLIにまつわる総合的な知識を要求されることになりました。文字列を復元するQ6は、まるでCTFの問題のようでした。

ちなみに、LT大会では初めてスライドというものを作りましたが、Markdown記法でスライドが簡単に作成できるMarp、おすすめの逸品です。

最後に、

に改めてお礼を申し上げます。ありがとうございました。

Written on November 1, 2016