Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
シェル芸人に必要なのは「マスキングテープ」だったのでは
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
greymd
June 27, 2020
Programming
11k
19
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
シェル芸人に必要なのは「マスキングテープ」だったのでは
2020/06/27 第48回シェル芸勉強会LT資料
https://www.youtube.com/watch?v=PIqx9fCSbaU&t=609s
greymd
June 27, 2020
More Decks by greymd
See All by greymd
Breaking Through Firewalls with Shell-gei
greymd
0
150
狂気!AWS CloudShell細胞分裂!
greymd
0
2.6k
毎日叩ける シェル芸を覚えよう!
greymd
4
4.5k
入門Cureutils
greymd
3
2.6k
Other Decks in Programming
See All in Programming
Vite+ Unified Toolchain for the Web
naokihaba
0
740
アルゴリズムは何を圧縮しているのか ─ Haskell から育った「圧縮代数」というメンタルモデル
naoya
16
3.3k
Generative UI & AI-Assistants for Your Angular Solutions
manfredsteyer
PRO
0
100
OSINT for SRE: 学術論文とポストモーテムから探る システム障害の共通パターン / SRE NEXT 2026
tomoyk
1
3.5k
エンジニアにデザインハーネスを 〜デザインプロセスを規定するためのハーネス〜 / Design harness from an engineer's perspective
rkaga
2
1.4k
The Bowling Game- From Imperative to Functional Programming - Part 1
philipschwarz
PRO
0
320
Performance Engineering for Everyone
elenatanasoiu
0
270
エンジニア向け会社紹介/Findy Company Profile
findyinc
6
360k
トークンをケチるな、設計しろ:GitHub Copilotを賢く使うコンテキスト戦略
ochtum
0
310
Honoでのサプライチェーン侵害対策 〜 3つのライブラリに学ぶ
yusukebe
7
1.8k
【やさしく解説 設計編・中級 #1】一つの車に、運転手は一人 ~ある倉庫システムの事例から~
panda728
PRO
0
170
言語を使う側から、作る側へ。 自作 Lisp で得た新たな気づき。
andpad
0
110
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
Mind Mapping
helmedeiros
PRO
1
280
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.8k
10 Git Anti Patterns You Should be Aware of
lemiorhan
PRO
659
62k
YesSQL, Process and Tooling at Scale
rocio
174
15k
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
The Spectacular Lies of Maps
axbom
PRO
1
850
Kristin Tynski - Automating Marketing Tasks With AI
techseoconnect
PRO
0
290
How to Ace a Technical Interview
jacobian
281
24k
Designing Powerful Visuals for Engaging Learning
tmiket
1
450
It's Worth the Effort
3n
188
29k
The Pragmatic Product Professional
lauravandoore
37
7.4k
Transcript
シェル芸⼈に必要なのは 「マスキングテープ」だったのでは ぐれさん
⾃⼰紹介 (1/3) ぐれさん (Twitter: @grethlen) シェル芸キュアエンジニア 危険シェル芸で国外追放された(⼤嘘) 最近良いことがあった
⾃⼰紹介 (2/3) 朗報 ※ 出典: 2020/06/21 放映「ヒーリングっど♡プリキュア」より
⾃⼰紹介 (3/3) Software Design シェル芸連載 「シェル芸⼈からの挑戦状」の連載 参加してました 2020 年 4
⽉号にて⼀旦終了 ※ STOPがかかったわけ ではないではない 150 問以上 ご愛読ありがとうございました!
シェル芸漬けの2年半 数多くの問題を解いたり考えたり 締切に追われて苦しみながら シェル芸⼈たちと頭をひねった2年半.. => ある法則に気づいた
こういう状況ありませんか 仕事や研究などで遭遇した困りごとをシェル芸で解決しようとするとき... ※ 出典: NHK健康チャンネル「発達障害って何だろう」より
「できるけど疲れる」問題1 第16回春だからログ解析するぞシェル芸勉強会 https://b.ueda.tech/?post=05644 準備1 ⼀部抜粋 ⽇付と時刻を次のように正規化しておきましょう。 ### 修正前### ueda@tencore:~/tmp/nasa$ zcat
access_log.nasa.gz | head -n 1 199.72.81.55 - - [01/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 ### 修正後### ueda@tencore:~/tmp/nasa$ cat access_log | head -n 1 19950701 000001 199.72.81.55 - - [01/Jul/1995:00:00:01 -0400] "GET /history/apollo/ HTTP/1.0" 200 6245 ※ 360 MB のファイルです
問題1 解答例 模範解答 zcat access_log.nasa.gz | awk '{print $4,$0}' |
sed 's/^\[//' | awk '{gsub(/[\/:]/," ",$1);print}' | awk '{$2=$2=="Jul"?"07":$2;$2=$2=="Aug"?"08":$2;print}' | sed 's;^\(..\) \(..\) \(....\) \(..\) \(..\) \(..\);\3\2\1 \4\5\6;' > access_log => AWK では⽉の名前(Jan, Feb...) => 数字の変換ができない date で⽇付の変換はできるのだが.. $ echo '01/Jul/1995:00:00:01 -0400' | sed 's|/| |g;s/:/ /' | date -f- +'%Y%m%d %H%M%S' 19950701 050001 => 事実上使えない(後述)
問題1 解答例(参加者抜粋) while でやった⼈ zcat access_log.nasa.gz | while read LINE;
do echo ${LINE} | sed 's/[^[]*\[//; s/].*//; s/-[0-9]\{4\}//; s/Jul/07/; s/Aug/08/;' | tr '/:' ' ' | awk '{printf($3$2$1" "$4$5$6" ")}'; echo $LINE; done => 解けるが、かなり時間かかる Ruby でやった⼈ zcat access_log.nasa.gz| ruby -EASCII-8BIT -rdate -ane '$F.unshift Date.parse($F[3]).strftime("%Y%m%d %H%M%S");puts $F*" "' => 解ける なお、ぐれさんは while + date で⾒事にマシンがホッカイロ(⽩⽬)
「できるけど疲れる」問題2 ぐれさんが実際に遭遇した問題イメージ(※ 脚⾊済み) 500 MB の CSV ファイルの4列⽬に名前がある これの姓と名の最初の⽂字を⼤⽂字にしたい 1,aaa,Hoge
team,yamada taro,2001 2,bbb,Super fuga team,ueda ryuchan,1998 3,ccc,N/A,toilet hanako,1998 ... ↓ 1,aaa,Hoge team,Yamada Taro,2001 2,bbb,Super fuga team,Ueda Ryuchan,1998 3,ccc,N/A,Toilet Hanako,1998 ...
問題2 解答例 名前単体の変換は次のでできる!でも sed はCSV読めないし..せや! $ echo yamada taro |
sed 's/\b./\U&/g' Yamada Taro 遅くて使い物にならない(涙) $ cat people.csv | while IFS=, read c1 c2 c3 c4 c5 ;do echo "$c1,$c2,$c3,$(echo "$c4" | sed 's/\b./\U&/g'),$c5" ;done $ cat people.csv | perl -F, -anle '{chomp($F[3]=`echo $F[3] | sed "s/\\b./\\U&/g"`); $,=","; print @F}' 結局 Perl でゴリ押しが現実的なソリューション.. cat people.csv | perl -F, -anle '{ $F[3] =~ s/(\b.)/\U$1/g; $,= ",";print @F}'
これらの問題の共通点はなんだろう? 元々の⼊⼒を残したまま⼀部分を書き換えている 処理対象が⼤きい データの加⼯⾃体は古典的なコマンドでできる でも使えないので、結局スクリプトでゴリ押しが現実解 => こんなの絶対おかしいよ!
「できるけど疲れる」原因は何か?(1) シェル芸の⾟い所(1): ⼤半のコマンドが「処理したくないデータの無視」ができない date , base64 , factor , iconv
, nkf , grep , fold , cut , ...
「できるけど疲れる」原因は何か?(2) シェル芸の⾟い所(2): 問題が複雑になるとスクリプティング地獄 「処理したくないデータの無視」ができるコマンドもあるが... awk , sed , perl ,
ruby , ... 「処理対象の選別」と「データの加⼯」がセット ⽴派なプログラミング⾔語 => ⾔語の制約に縛られる ⾔語の仕様や技法・ライブラリに明るい必要がある => いざというときサクッとできない
補⾜:「処理対象の選別」と「データの加⼯」がセット GNU sed ... | sed '/AAA/,/BBB/{ s/hoge/fuga/g }' GNU
Awk ... | awk '{gsub("A","B",$1);gsub("B","C",$3);print}' Perl ... | perl -nle '/^(......)(...)/; $a=$1;$b=$2; $b =~ s/./@/g; print "$a$b"'
「できるけど疲れる」原因は何か?(3) シェル芸の⾟い所(3): スクリプティング地獄を解消しようとするとfork地獄に陥る Bash の while ⽂ sed、AWK等の内部から別のコマンドを外部コマンドとして呼び出す ⼤量のデータ処理には向かない
シェル芸⼈のジレンマ スクリプティング地獄 ↔ fork地獄 とてもつらい
シェルとコマンドのアプローチを振り返る パイプ コマンド同⼠をべったりとくっつける糊 どこを処理するかはコマンドにおまかせ UNIX のコマンド 標準⼊⼒を「丸ごと」受け取って処理するコマンドが⼤半 糊につける「マスキングテープ」があればどうだろう? 「べったり」ではなく「⼀部分のみ」 残りの部分は「そのまま」
世の中の問題はシンプルになるのではないか
teip コマンド シェル環境で使えるマスキングテープ [URL] https://github.com/greymd/teip macOS brew install greymd/tools/teip DEB
file git.io/teip-1.2.0.x86_64.deb RPM file git.io/teip-1.2.0.x86_64.rpm Cargo(要 libclang ) cargo install teip
teip はなにができるか teip < フィルタリングルール> -- < コマンド> < フィルタリングルール>
: 標準⼊⼒のどの部分を < コマンド> に渡すか設定 < コマンド> : 標準⼊⼒まるごとは受け取る必要はない < フィルタリングルール> にマッチしなかった個所 => そのまま出⼒ < フィルタリングルール> にマッチした個所 場所はそのままだが < コマンド> の結果と置換される
teip の基本的な使い⽅ ※ デモ ※ README の Getting Started の内容を紹介
teip で先程の問題を解く ※ デモ 問題1 $ zcat access_log.nasa.gz | awk
'{print $4,$0}' | sed 's/^\[//' | teip -f 1 sh -c "sed 's|/| |g;s/:/ /' | date -f- +'%Y%m%d %H%M%S'" 問題2 $ cat people.csv | teip -d, -f4 sed 's/\b./\U&/g'
こういう問題も解ける(時間があればデモ) 第30回危念シェル芸勉強会 https://b.ueda.tech/?post=10134 Q2 ⼀部抜粋 リンクが相対パスになっているものについては頭に/files/をつけて、/から始まっているも のとhttpやhttpsから始まっているものはそのままにしてください。 (.. 略..) <li><a
href="./hoge.html"> ほげ</a></li> <li><img src="ayasii.jpg" alt=" 怪しい" /></li> <li><a href="https://blog.ueda.tech/"> クソブログ</a><a href="huge.html"> ふげ</a></li> <li><a href="/root.jpg"></a> これはそのまま</li> <li><a href="http://www.usptomo.com/"> 更新してない</a></li> (.. 略..)
解答例 sed が同じ⾏を書き換えてしまうのが⾟い $ cat url.html | sed -r 's;(img
src="|a href=");&/files/;g' | sed -r 's;(href="|src=")/files//;\\1/;' | sed -r 's;(href="|src=")/files/(https://|http://);\\1\\2;g' | sed 's;/./;/;g' 他の参加者の解答 perl -ple 's@[fc]="(?!(?:https?://|/))(?:./)?(.*?)"@="/files/$1"@g' url.html sed 's,\([fc]="\)\(\./\)\?\([^/][^":]*\)",\1/files/\3",' url.html sed -r -e 's@((href|src)=)([^/])@\1/files/\2@g' -e 's@/files/http@http@g' url.html
解答例(teip) 短く解こうと思えばできる $ cat url.html | teip -Gog '[fc]="(?!(https?|/))\K.*?(?=")' --
sed 's|[./]*|/files/|' => ⻤⾞正規表現が使える( -G ) テープの重ねがけ $ cat url.html | teip -og '(a href|img src)=".*?"' \ -- teip -og '".*"' \ -- teip -og '[^"]+' \ -- teip -vg http \ -- teip -vg '^/' \ -- sed 's|[./]*|/files/|' => 正規表現の AND 条件(!)... 表現⼒は超強⼒
teip のパフォーマンス 細かくベンチマークをとりながら Rust で開発 実⾏対象のコマンドは使い回す => fork しないので早い(※ )
実⾏コマンドの標準⼊出⼒をプロキシ 複数プロセス並列実⾏ ⼀時ファイルなし I/O は極⼒バッファリング => 無駄なシステムコールを削る ※ 都度forkする動作も選択可能
なぜ Rust か 速度・並⾏性に定評があるコンパイル型⾔語 Rust 製 Coreutils(uutils/coreutils)あり 性能をベンチマーク => 本家に負けず劣らず
=> ヒーリングっどきた Cの資産の取り回しも悪くない 例: ⻤⾞正規表現 Cの共有ライブラリも⼀緒にビルド
teip vs GNU grep 数百100MBのファイルの⾏頭から30⽂字に 拡張正規表現で⾊をつける謎の速さ対決 ※ ページキャッシュ消すのを忘れずに $ time
grep --color=always -E '^.{30}' < test_secure | pv > /dev/null $ time teip -og '^.{30}' < test_secure | pv > /dev/null => デモ
注意: teip単体で⼗分な⽔準のI/O速度を出せる点のアピール以上の意図は無い ユースケースが異なるものを⽐較してもあまり意味はない teipはまだまだ⽣まれたばかりのソフト いわゆる「第⼀のシステム」※ 成熟したソフトより速度が早い状況は「あるある」
※ 芳尾 桂 (翻訳) Mike Gancarz (著). UNIX という考え⽅― その設計思想と哲学.
オーム社, 2001.
ベンチマーク (1) なので、こんなベンチマークはどうでしょう? GNU sed vs GNU sed (+ teip)
$ sed -r 's/< 正規表現>/.../g' < ファイル $ teip -og '< 正規表現>' -- sed -r 's/< 正規表現>/.../g' < ファイル GNU Awk vs GNU Awk (+ teip) $ awk '{gsub("< 正規表現>","...",$0);print}' < ファイル $ teip -og '< 正規表現>' -- awk '{gsub("< 正規表現>","...",$0);print}' < ファイル ※ < 正規表現> はすべて同じもの
ベンチマーク (2) ⼤きなファイルのIPアドレスを置換 上: 置換前 下: 置換後
ベンチマーク (3) $ teip -og '< 正規表現>' -- awk '{print
"..."}' < ファイル $ teip -og '< 正規表現>' -- sed -n 'i...' < ファイル teip があるから実現可能な効率的な⽅法 よりフェアな⽐較(?) 正規表現の実⾏は1回のみ
0 2 4 6 8 10 awk sed teip +
awk teip + sed teip + awk (print) teip + sed (i text) Total Runtime(sec) 8.390 5.393 4.306 3.795 2.106 1.836 ※ 詳細・追試⽅法は https://github.com/greymd/teip/wiki/Benchmark
まとめ シェル芸は「処理したくないデータの無視」が苦⼿ 「処理対象の選別」と「データの加⼯」が癒着してた 複雑な問題では、スクリプティング地獄 あるいはfork地獄 teip とは 「⼀つのこと」(処理対象の選別)をうまくやる 問題の解法がシンプルになる オマケに「処理対象の選別」と「データの加⼯」を並列化できる
性能向上が図れる
今後の展望 teip のこれから sed の /AAA/,/BBB/ みたいなのがほしい sed みたいにN倍数の⾏数のみ、とか(ほしいです?) これで仕事が楽になる⼈は多い気がするので布教
エネルギーの浪費で地球環境に悪い 地球をお⼿当て、そう今のプリキュアのように ああああプリキュアが⾒たいいいいしぬんじゃぁ ぼやき まてよ、Rust 製 Coreutils があるなら、Cureutils がないとおかしいのでは? Rustめっちゃいい。。egzact 作り直そうか。。どうしても遅いよぉ。。