2016/10/29

第25回シェル芸勉強会参加報告

2016-10-29(土)に開催された、第25回シェル芸勉強会(正式名称:jus共催 第7回初心者の定義で大揉め午前のシェル勉強会/第25回もう4年もやってんのかシェル芸勉強会)に参加しました。
ただ、在住地の関係で直接会場へ伺うことは出来なかったため、Youtubeで配信してくださったライブ中継を利用して、遠隔で参加しました。

勉強会は、午前と午後の2部構成でした。
午前は、シェルに関する勉強会で、manページ用いた読書勉強会でした。
午後は、シェル芸勉強会で、シェル芸力を付けるための問題を解きました。

以下、勉強会の詳細を記します。


実行環境

  • Arch Linux 4.8.4-1-ARCH

  • GNU bash 4.3.46

  • GNU coreutils 8.25-2

  • GNU diffutils 3.5-1

  • GNU findutils 4.6.0-2

  • util-linux 2.28.2-1

  • grep (GNU grep) 2.26

  • sed (GNU sed) 4.2.2

  • gawk 4.1.4

  • nkf 2.1.4

  • xxd V1.10 27oct98

  • gnuplot 5.0


シェルに関する勉強会

manページ読書会

シェル芸おじさんこと、USP友の会 会長の上田 隆一( @ryuichiueda )さんによる、manページを読んでコマンドへの理解を深める内容でした。
今回は、有名なUnixコマンド、grepに関して、manページを読み進めました。
頻繁に使用するコマンドなので、分かりきっていると思っていたけれど…​
改めてきちんとmanページを読んでみると、まだまだ知らないことだらけだったり。

以下、個人的に気になった内容。

  • GNU grepのfgrep egrepは、実はシェルスクリプトになっていて、中でgrepをオプション付きで呼び出しているだけ
    → BSDのgrepは、fgrep egrep共にバイナリだった。

  • GNU grepは、処理速度が非常に高速で、GNU脱却を目指しているFreeBSDプロジェクトでも、なかなかリストラ出来ないとか
    → 参考: 第74回 FreeBSD 12,GNU rcsをベースから削除:BSD界隈四方山話|gihyo.jp … 技術評論社

  • -Fオプションは、単純なフィルタ処理をおこなう分、処理速度やメモリ消費に優れる

  • -eオプションを使うことで、複数のパターンを指定できる
    例:

$ echo -e 'hoge\nhage\nhige' | grep -e 'hoge' -e 'hige'
hoge
hige
  • -qオプションを使うことで、条件分岐に利用できる
    例:

$ cat profile
身長 178
体重 68
髪の毛 none
$ [ $(grep -q 'none' profile) ] || echo 'hage'
hage
$ wc -l hoge
3000000000 hoge
$ head hoge
1
2
3
4
5
6
7
8
9
10
$ time grep '404' hoge >/dev/null
real    0m0.013s
user    0m0.007s
sys     0m0.003s
$ time grep -F '404' hoge >/dev/null
real    0m0.009s
user    0m0.003s
sys     0m0.003s
結果

-Fオプションを付けたほうが、(ちょっとだけ)速いらしい。

また、 @MasWagさんによれば、grep -Fは、 エイホ–コラシック法で実装されている(いた?)らしい。

第25回シェル芸勉強会

問題文および模範解答は、以下のURLから。
https://blog.ueda.asia/?p=8737

問1

www.usptomo.com のIPアドレスを調べる問題。

digるなり、pingるなり、nslookupるなり。
てか、digに+shortなんてオプションがあったのね…​

01 #!/bin/sh
02
03 dig www.usptomo.com                 |
04 sed -n '/ANSWER SECTION/{n; p}'     |
05 awk '$0=$NF'

以下、コピペ実行用のワンライナーコード。

dig www.usptomo.com | sed -n '/ANSWER SECTION/{n; p}' | awk '$0=$NF'

問2

前日 の復習(?)問題。

「響け!ユーフォニアム」と同じコードで。
awkを使って、堅実に出力する。
変態的な解答をお探しの方は、上記のTogetterまとめへどうぞ…​w

01 #!/bin/sh
02
03 echo ひらけ!ポンキッキ               |
04 awk -vFS= '$1=$1'                     |
05 awk '{for(i=1;i<=NF;i++){print}}'     |
06 awk '{for(i=NR;i<=NF;i++){printf $i}; for(i=1;i<NR;i++){printf $i}; print ""}'

以下、コピペ実行用のワンライナーコード。

echo ひらけ!ポンキッキ | awk -vFS= '$1=$1' | awk '{for(i=1;i<=NF;i++){print}}' | awk '{for(i=NR;i<=NF;i++){printf $i}; for(i=1;i<NR;i++){printf $i}; print ""}'

問3

リダイレクトを制限した状態で、特定ファイルをフィルタした結果を、ファイルへ書き出す問題。

僕の環境では、rbashは存在しなかったので、同様の機能を持つ以下のコマンドで代用した。

$ bash -r

幾つかのコマンドは、自身でファイルに出力する機能を持っているので、リダイレクトの代わりにそれらを利用すればOK。

awkのリダイレクト機能で。

01 #!/bin/sh
02
03 cat /etc/passwd     |
04 awk -F: '$NF ~ /bash/{print > "hoge"}'

sedのwコマンドで。

01 #!/bin/sh
02
03 cat /etc/passwd     |
04 sed -n '/\/bin\/bash$/w hoge'

以下、コピペ実行用のワンライナーコード。

cat /etc/passwd | awk -F: '$NF ~ /bash/{print > "hoge"}'
cat /etc/passwd | sed -n '/\/bin\/bash$/w hoge'

問4

ひらがな文字列に濁点をつける問題。

nkfだけだと難しかったので、Tukubaiを解禁。
いったん半角カナに変換し、その状態で全ての文字に半角濁点を付加する。
その後、全角カナに戻せば、濁点がつけれる文字は濁点付きに、そうでない文字は、元の文字+全角濁点になる。
後は、余分な全角濁点を除去し、出力を整形すればOK。

01 #!/bin/sh
02
03 echo すけふぇにんけん     |
04 nkf --katakana            |
05 han                       |
06 sed 's/./&゙/g'            |
07 zen                       |
08 nkf --hiragana            |
09 sed 's/″//g'

以下、コピペ実行用のワンライナーコード。

echo すけふぇにんけん | nkf --katakana | han | sed 's/./&゙/g'  | zen | nkf --hiragana | sed 's/″//g'

ちなみに、nkfにも全角 → 半角変換をおこなう機能、-Z4オプションなんてものがあるそう。
ただ、この-Z4オプションは、残念ながらmanページには書かれていないみたい…​
(nkf --helpすると、一応記載はされているようだけれど。)

問5

進捗状況のようなアニメーションを作る問題。

実はこの問題、題意をちょっと勘違いしていた…​
僕の環境では、ブラウザ上で「ファイルをダウンロード」と表示されていたので、てっきりダウンロード画面のようなアニメーションを作ると思っていた。
でも、実際には、1秒毎に"*"の文字が増えるだけで良かったらしい。

01 #!/bin/sh
02
03 seq 1 inf                                                                                                                 |
04 awk '{printf "clear; echo ファイルをダウンロード; echo '\''"; for(i=1;i<=$0;i++){printf "*"}; print "'\''; sleep 1"}'     |
05 sh

せっかくなので、もっとシンプルなバージョンを。

01 #!/bin/sh
02
03 yes 'printf "*"; sleep 1'     |
04 sh

以下、コピペ実行用のワンライナーコード。

seq 1 inf | awk '{printf "clear; echo ファイルをダウンロード; echo '\''"; for(i=1;i<=$0;i++){printf "*"}; print "'\''; sleep 1"}' | sh
yes 'printf "*"; sleep 1' | sh

問6

暗号化された文字列を復元する問題。

この問題は、今回の勉強会で全く歯が立たなかった…​orz
分かる人には分かるそうだけれど、暗号文がリトルエンディアンになっているとの事。
…​ごめんなさい、僕には見ただけでは分からなかったですw

という訳で、模範解答を参考にしつつ、改めて正答を考えてみた。

01 #!/bin/sh
02
03 cat crypt                       |
04 sed 's/\(..\)\(..\)/\2\1/g'     |
05 xxd -r -p                       |
06 nkf -W16

以下、コピペ実行用のワンライナーコード。

cat crypt | sed 's/\(..\)\(..\)/\2\1/g' | xxd -r -p | nkf -W16

問7

2016年10月29日の範囲の秒数で、UNIX時間で素数になるものを出力する問題。

これは、 シェル芸スパルタン演習第9回で似たような問題をやったので、余裕だぜ…​!!

01 #!/bin/sh
02
03 seq $(date -u --date 20161029 +%s) $(date -u --date 20161030 +%s)     |
04 sed '$d'                                                              |
05 factor                                                                |
06 awk 'NF==2&&$0=$2'                                                    |
07 xargs -n1 -I% date -u --date @%

以下、コピペ実行用のワンライナーコード。

seq $(date -u --date 20161029 +%s) $(date -u --date 20161030 +%s) | sed '$d' | factor | awk 'NF==2&&$0=$2' | xargs -n1 -I% date -u --date @%

問8

CLI上で正弦波を出力する問題。

この問題は、個人的に問6の次に難しかった…​
というのも、一応理系出身なのに、数学はさっぱりなので…​orz

…​なので、横着してgnuplotさんに正弦波を出してもらった♥

01 #!/bin/bash
02
03 gnuplot <(echo -e 'set terminal dumb\nplot sin(x)')

以下、コピペ実行用のワンライナーコード。

gnuplot <(echo -e 'set terminal dumb\nplot sin(x)')

正攻法な解法は…​…​勘弁してくださいorz

雑記



多少はシェル芸が分かるようになったし、僕自身の状況も少し落ち着いてきたので、そろそろ名古屋サテライト会場について考えてみたかったり。
とはいえ、勉強会を開催した経験は無いし、そもそも中度のコミュ症なので、果たして主催なんて出来るのかという不安もあったり…​…​ _(:3」∠)_
まあ、焦らずのんびりと考えていきたいと思っています。

いつも遠隔での参加になってしまいますが、毎回とても楽しめているうえに、新しい発見ばかりで、非常に勉強になります。
勉強会を開催してくださった、上田会長をはじめとした日本UNIXユーザ会とUSP友の会の皆様、今回もありがとうございました!!

Tags: シェル芸 Unix
このエントリーをはてなブックマークに追加