日々之迷歩

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

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

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

起きるとそこは雪国でした。ここは福岡県です。寒さに負けて引き篭もっていたい気持ちがありますが、電車に乗るため駅へと向かうのでした。目的地はシェル芸勉強会の福岡サテライト会場です。今回の会場はベータソフト様会議室を使わせていただきました。8人の参加者が集いました。 問題作成と解説の上田さん、ありがとうございます。参加者の皆様もお疲れ様でした。

sites.google.com

勉強会の情報

勉強会主催者の上田さんが公開されているページをご覧ください。 b.ueda.tech

午前の部

参加者の方にsedの習熟度を質問させていただいたところ、それほど使い込んでいない方が多いようでした。 そこで福岡サテライト会場では、午前の部を独自に進めることにしました。 午後からのsed問題に備えて、sedの基礎知識から中級編のネタについて話をしました。

  • GNU sedとBSD付属sed
  • 1d;$d などの行番号とdコマンドの組み合わせ
  • -n オプションで出力の抑止
  • 1,3 /<table/<\/table>/ などの範囲指定
  • yコマンドを使った変換とtrコマンドとの比較
  • echo 12345 | sed 's/^\(.\).*$/\2\1/' のようなsコマンドの置換と後方参照
  • find . -type f | sed 's;.*;cp -p & DIR;' のような繰り返しコマンド列を作る技
  • 羊を100匹数えるコマンド列の作成(SoftwareDesignの記事)
  • ラベルを使った繰り返し
  • ホールドスペースを使ってtacコマンドの実装(行を逆順に)
  • sed pの繰り返しで倍々ゲーム
  • sedでFizzBuzz
  • Apacheログファイルの日時正規化
  • その他シェル芸勉強会やTwitterで流れたsedの面白ネタ。

一通りsedの機能について話をした後、sedの元になったedの簡単なデモをやってみました。 grepコマンドについては、名前の語源や使いかたコマンドについても説明しました。(g/^1/p => g/正規表現/p => g/RE/p => grep

$ seq 10 > temp

$ cat temp
1
2
3
4
5
6
7
8
9
10

$ ed temp 
21      ## ファイルのバイト数表示
g/^1/p  ## grepコマンドの名前の語源 ##
1
10
5p      ## 5行目表示
5
1d      ## 1行目削除
$d      ## 最終行削除
w       ## 保存
16      ## 保存後のファイルバイト表示
q       ## ed終了

$ cat temp 
2
3
4
5
6
7
8
9

sedのパターンスペースとホールドスペースの図解は、こちらの記事に詳しく記載されておりましたのでご覧ください。 qiita.com

昼食

参加者みんなで近くの餃子の王将へ行きました。 途中で世界的に有名になった「博多の大穴」が出来ていた横断歩道を渡しました。しかし事故やけが人がいなかったのは本当に良かったですね。

昼食を食べながら、仮想化やクラウド化が進み利便性が向上したけど、教育という面では逆に難しくなった面もあるかもねーみたいなお話をしたりしました。抽象度が上がると入門者にとっては実感がわかずかえって難解になってしまうかもしれず、難しいですね。

午後の部

午後の部が始まる前に、イントロのスライドで話をさせていただきました。勉強会に興味を持っていただきありがとうございます。

speakerdeck.com

いよいよsed地獄?の始まりです。午前中にsedの話をしておいてよかったですね。

下記解答例はmacOSを使っているため、GNU sedはgsedコマンドになっているので注意でう。Linuxの人はsedに読み替えてください。

Q1

一文字ずつ飛ばしてアルファベットを大文字に変換する問題。 これは福岡サテライト参加者の方から解答が出ました。 大文字へ変換する\Uに後方参照を組み合わせて\U\2のようにする回答で、出題者上田さんの解答例と同じでした。

Q2

やっぱり出ました、sedでFizzBuzzです。

### GNU sedで
$ seq 100 | gsed '3~3s/$/ Fizz/' | gsed '5~5s/$/ Buzz/' | gsed '/z$/s/^[0-9]* //'
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz Buzz
....

### BSD sedで
$ seq 20 | sed 'n;n;s/$/ Fizz/' | sed 'n;n;n;n;s/$/ Buzz/' | sed '/z$/s/^[0-9]* //'
1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
Fizz Buzz
.....

Q3

3行目を7行目の下に移動。下記のような解答を出しましたが、出題者上田さんの解答とほぼ同じでした。 今回の場合は最後の7g7xでも良かったですね。

$ seq 10 | sed '3h;3d;7p;7g'
1
2
4
5
6
7
3
8
9
10

Q4

c++のソースファイルをコンパイル可能にしろというお題。 関数宣言する前に関数を使ってるため、目的の関数をmain関数の前に移動します。 出題者上田さんの解答と同じでした。

Q5

2行ずつ入れ替えろというお題。sedを使わない解答を先に思いつきました。

$ seq 10 | xargs -n 2 | awk '{print $2,$1}' | xargs -n 1
2
1
4
3
6
5
8
7
10
9

次の行に移動するnコマンドやホールドスペースを使う必要がありそうですが、結局下記の間違い解答しか思いつきませんでした。

$ seq 10 | sed 'h;n;G'
1
2
1
3
4
3
5
6
5
7
8
7
9
10
9

出題者上田さんの解答は、奇数行と偶数行で処理を分けて考えられていました。

  • 奇数行:ホールドスペースにコピーしてパターンスペースを削除
  • 偶数行:ホールドスペースをパターンスペースに追記

上田さんが「問題と解答」のページに解答例を記載されていますが、解説中に更にまとめた解答例を解説されていました。 下記に記載させていただきます。 ホールドスペースをパターンスペースに追記する処理については、偶数行の指定は不要みたいですね。

$ seq 10 | gsed '1~2{h;d};G'
2
1
4
3
6
5
8
7
10
9

Q6

出題者上田さんの解答と考え方は似ていました。GNU sedのラベル機能を使った繰り返し処理です。 私の解答はtコマンドで無限ループを使うので、headコマンドで強制的に10行に切り詰めています。

$ echo 1 | gsed ':l;p;s/.$/&&/;tl' | head
1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111

上田さんの解答では、bコマンドで条件付き繰り返しを使っていました。これは便利そうですね。

詳しくはSoftware Design 2017年1月号のシェル特集をご覧ください。

今回の勉強会がsed地獄になったきっかけは、上記Software Designの共同執筆中に起きた事件が元らしいです。@ebanさんによるsedのラベルを使った繰り返し処理の解答が出てきて、執筆陣の間で「ナンダコレワ??」と戦慄が走ったのを思い出しました。

Q7

縛り1の解答は出題者上田さんと同じでした。GNU sedのeコマンドで解決です。

縛り2の解答はギブアップでした。10回の繰り返しを数字を使わず指定するにはheadコマンド使えば良さそうなのですが?? sedに行数を表示する=というコマンドがあるということを知りました。

Q8

上側半分を作るのはQ6と同じですね。後半をどうするかですが、ラベルを2つ使ったループを考えました。

$ echo 1 | gsed ':LOOP1; p;s/.$/&&/;/.\{5\}/!bLOOP1;p; :LOOP2; p;s/.$//;/^.$/!bLOOP2'
1
11
111
1111
11111
11111
1111
111
11
1

出題者上田さんの解答は、前半の出力をひっくり返してケツに追加するという考え方でした。 sedのGhコマンドを繰り返して、行を逆順にしていく技の応用になるようです。

行順をひっくり返すtacコマンドの動きをsedでやる件については、大阪サテライト会場担当のid:kunst1080さん記事をご覧ください。 www.kunst1080.net

午後の部終了後

午後の部終了後、軽く問題のおさらいをしました。その後仮想端末のtmuxについて話をしました。と言っても、私もまだ使い始めたばかりなのですが。

speakerdeck.com

tmux起動時に自動的にWindow作成やpane分割、コマンド実行など出来るのか、確認したいですね。 またコピーモードやスクロール操作がまだあまり理解出来ていません。

今回は午前中にsedの話をしておいてよかったです。話す内容をある程度まとめておいたので、ある程度スムーズに話が出来たとは思います。 福岡サテライト会場ではサポートが重要だと思うので、今後も午前中はどういうやり方がいいか試行錯誤していきたいと思います。 参加者の方々は、自分なりのペースで何かを掴んでいっていただけると幸いです。