SlideShare a Scribd company logo
1 of 83
Download to read offline
はじめよう、シェル芸
~シェル芸ってなぁに?~
2020.05.23
オープンキャンプ in 南島原 2020 Online
自己紹介
● 名前 大西 尚利(おおにし・ひさとし)
● 所属 ある都内のIT企業に所属にて、最近流行りの
   SRE的な業務をやってます。神奈川県在住。
今回紹介する「シェル芸」経験は約4年程度
⇒但し、スゴい技は持ち合わせていません…
はじめに
「シェル芸」を紹介するにあたって
皆さんにお伺いいたします…
はじめに
はじめに
【質問】
UNIX系OSで日常的にコマンドを触っている。
または、その作業に抵抗がない。
はじめに
【質問】
シェル芸とは何か?を知っている
はじめに
【質問】
実は、既にシェル芸勉強会に出席した実績がある
はじめに
【質問】
実は、私がシェル芸人だ(自称でもOK)
FAQ?
(よくある…かもしれない質問)
よくある…かもしれない質問
【Q】シェル芸ってなんですか?
「シェル芸」の定義として、以下のようなものがあります。
マウスも使わず、ソースコードも残さず、GUIツールを立ち上げ
る間もなく、あらゆる調査・計算・テキスト処理をCLI端末へのコ
マンド入力一撃で終わらすこと、あるいはその時のコマンド入力
のこと。(USP友の会会長・上田隆一氏による定義)
よくある…かもしれない質問
【Q】シェル芸を身に付けると、役に立つことはありますか?
基本的にありません。但し、習得するうちに何らかの「気付き」
があるかもしれません(が、もちろん無保証です)。
● コマンドライン中心の作業が怖くなくなります。
● 普段使っているコマンドの様々なオプションの存在を再発見で
きます。
● 正規表現をはじめ、文字列の処理に強くなれます。
よくある…かもしれない質問
【Q】シェル芸で「不都合な真実」に晒される危険性は?
下記のような例が挙げられます。
● 実行するコマンドが難解になり、周りから奇異な目で見られる
可能性があります。
● どんなデータ処理も、コマンドラインで行わなければ気が済ま
なくなる場合があります。
● 色んな意味で注目を浴びるようになる可能性があります。
よくある…かもしれない質問
【Q】表紙にもあった、このイラスト(→)は何ですか?
→ 「USP友の会」のマスコットで、名前は「ちんじゅう
ちゃん」とのことです。なお、ムササビではないそう
です(似てますけどね…)。
→詳しくはコチラ
 https://www.usptomo.com/PAGE=20101025FAQ
よくある…かもしれない質問
【Q】シェル芸は、Unix系システムでないと出来ないのですか?
→ 今回はUbuntu上のbashでの実行を前提としていますが、様々
なプラットフォームで試されている方もおります。
● Javascript
● PowerShell (Windows)
● Vim
● その他(標準入出力とパイプがあれば…)
「シェル芸」とは?
「シェル芸」とは?
シェル芸は、コマンドをパイプでつなぐことから始まります。
ファイル削除の実績をコマンド履歴から確認する
システムログの更新分からerrorを探して表示する(大/小文字不問)
CSVから第1フィールドだけを抜きだし、それらの個数を集計する
$ history | grep rm | less
$ tail -f /var/log/messages | grep -i error
$ cat hogehoge.csv | awk -F, ‘{print $1}’ | sort | uniq -c
「シェル芸」とは?
応用すると、こんなこともできます(別途コマンド群をインストー
ルする必要のあるものを含む)。
● 繰り返し定型作業の一括処理
● CSVファイルなどの集計
● 定型フォーマットを持つ各種ドキュメントの大量生成
● 図形描画や画像生成
「シェル芸」とは?
Git の脆弱性診断に(難読化)シェル芸が登場したことも…
2017/08/11に発表された「gitコマンドの脆弱性」に該当するgit
かどうかを手っ取り早く確認する方法として話題を呼びました。
さすがに現在は、対象となるようなgitが残っ
ているとは思えませんので、当時の対象環境
で出力された状態を再現するためのコマンド
だけを紹介します。
「シェル芸勉強会」のご案内
「シェル芸勉強会」のご案内
今回はオンライン出張版での開催ですが、ほぼ隔月のペースで勉
強会を開催しています(次回は2020/06中~下旬の見込み)。
オンサイト会場は東京(新宿)となっておりますが、大阪・松江・
福岡・長崎などにサテライト会場が出現することがあります。
https://usptomo.doorkeeper.jp/ (勉強会申込ページ)
ハッシュタグ「#シェル芸」でTwitterを見守る方法もアリです。
《とび入り参加歓迎!》
「シェル芸勉強会」のご案内
これまでの問題と解答は、同勉強会を主宰されている上田先生の
ブログからご覧になれます(関連ファイルもgithubにあります)。
上田ブログ:シェル芸勉強会問題一覧
https://b.ueda.tech/?page=00684
「シェル芸勉強会」のご案内
過去の勉強会の様子は、YouTubeに放置で公開されています。
シェル芸チャンネル
https://www.youtube.com/channel/
UCNnuBjHrb2UYBUi0I5otmjQ
【デモ】シェル芸の事例紹介
シェル芸の事例紹介
実際に「シェル芸」の作品を幾つか御覧に入れたいと思います。
● ほぼ理解不能なコマンド
● うねうね、うねうね… 暗記と詠唱には不向きなもの
には、それぞれのコードを元
にQRコード化した画像を掲載
しています。
※QRコードは株式会社デンソーウェー
ブの登録商標です。
シェル芸の事例紹介
シェル芸を始めると、ごく普通の命令文を羅列するだけでは飽き
足らない…という人が出てきます。
● 特定のファイル上の文字列からコマンドを生成
● コマンドらしからぬコマンドを作成
● 一般には知られていないオプションで予想外な動作を開拓
いろいろなdateコマンド
以下のコードは、どれもdateコマンドが実行されます。
lsコマンドの特定行から所望の文字を抜き出す
Base64形式に変換したものをデコード
16進数の文字コードでコマンド入力
もはや解説不能…?
$ $(ls --help | grep ^M | cut -c 4-6,16)
$ echo -e "x64x61x74x65"| bash
$ $(echo "ZGF0ZQo=" | base64 -d)
$ $(echo -n "そずねぞ" | base64 | grep -o '[a-z]' | tr -d n)
“ls --help“が”date”になるまで
”ls –help”がなぜ”date”へと変化するのか。
ここでは、コマンド群を少しずつ「巻き戻し」ながら、何が起こっているのか
を見てみます。
まずは、シェルに出力内容を渡すようにしていた外側の”$(~)”を取り去ってみ
ました。確かに”date”となっています。
$ ls --help | grep ^M | cut -c 4-6,16
date
$ $(ls --help | grep ^M | cut -c 4-6,16)
“ls --help“が”date”になるまで
つづいて、”cut”命令を取り除いてみます。
ここで残る”ls --help”は、言わずと知れた「”ls”コマンドの使用法」ですが、敢
えてパイプを介して”grep ^M”としています。この結果を見てみましょう。
なんと、”date”を構成可能な”dat”(4~6文字目)と”e”(16文字目)が存在してい
ます(該当箇所を赤文字強調しています)。
なお、大文字の”M”で始まる行は、現時点ではこの行が唯一のものとされてい
ます(恐らくは、長年にわたってこの状態かと思われます)。
$ ls --help | grep ^M
Mandatory arguments to long options are mandatory for...(略)
BASE64形式とデコード
謎の文字列”ZGF0ZQo=”の正体ですが、タイトルにある通り、BASE64形式に
変換された”date”という文字列です。
実行結果をそのままシェルに出力内容を渡すようにしていた外側の”$(~)”を取
り去って実行すると、何が出力されていたかが分かります。
$ $(echo "ZGF0ZQo=" | base64 -d)
$ echo "ZGF0ZQo=" | base64 -d
date
BASE64形式とデコード
なお、この「謎の文字列」を手っ取り早く手に入れるには、上記のように変換
したい文字列をBASE64形式に変換する方法が一番簡単です。
$ echo "date" | base64
ZGF0ZQo=
ASCIIコードを利用する
まず「”x64x61x74x65”って何?」と思われた方も少なくな
いと思います。
これはACSIIコードと言い、半角英数字(と機能文字など)に割り当
てられたごく基本的な文字コードです。
$ echo -e "x64x61x74x65"| bash
ASCIIコードを利用する
ここで使われている4つはそれぞれ”x64(d)”、”x61(a)”、
”x74(t)”、”x65(e)”を指します。
実際にこれらの表示を行う”echo”命令だけにすると、何をしてい
るかが一目瞭然となります。
この結果をシェルへ渡せば、無事(?)に”date”コマンドが実行さ
れるのです。
$ echo -e "x64x61x74x65"
date
ASCIIコードを利用する
0 1 2 3 4 5 6 7
0 NUL DLE SP 0 @ P ` p
1 SOH DC1 ! 1 A Q a q
2 STX DC2 “ 2 B R b r
3 ETX DC3 # 3 C S c s
4 EOT DC4 $ 4 D T d t
5 ENQ NAK % 5 E U e u
6 ACK SYN & 6 F V f v
7 BEL ETB ‘ 7 G W g w
8 BS CAN ( 8 H X h x
9 HT EM ) 9 I Y i y
A LF SUB * : J Z j z
B VT ESC + ; K [ k {
C FF FS , < L  l |
D CR GS - = M ] m }
E SO RS . > N ^ n ~
F SI US / ? O _ o DEL
「そずねぞ」の怪
これのコマンドがどのように”date”への変化するのか、順を追って
みてみましょう。
ここで出力された文字列をみてお気づきの方も多いかと思います
が、この段階で既に ”d” ”a” ”t” ”e” の4文字が出てきています。
この出力結果から1文字ずつ評価して英小文字だけを取り出してい
るのが、”grep -o ‘[a-z]’”コマンドです。
$ $(echo -n "そずねぞ" | base64 | grep -o '[a-z]' | tr -d n)
$ echo -n "そずねぞ" | base64
44Gd44Ga44Gt44Ge
$ $(echo -n "そずねぞ" | base64 | grep -o '[a-z]' | tr -d n)
「そずねぞ」の怪
但し、この出力では1行あたり1文字になっていますので、そのま
まではコマンドとして到底使える代物ではありません。
ここで出力された文字列をみてお気づきの方も多いかと思います
が、この段階で既に ”d” ”a” ”t” ”e” の4文字が出てきています。
$ $(echo -n "そずねぞ" | base64 | grep -o '[a-z]' | tr -d n)$ echo -n "そずねぞ" | base64 | grep -o '[a-z]'
d
a
t
e
$ echo -n "そずねぞ" | base64 | grep -o '[a-z]' | tr -d n
date
ドキッ!”\”だらけの素数出力命令
以下のコードを実行すると、なぜか「2~1000の範囲に存在する
素数を表示」します。
eval eval ''n='''{1..'$(dc -e 1000vp)'}
''' eval eval eval echo '''
''''$(( '''''''$n
'''''''*''''
''''{2..$((1000/n))}'''
'''''))
''''''';'' |
tr ' ' n | sort -n | uniq -u
※このコードは改行の都合で動作しません。QRコードをどうぞ。
ドキッ!”\”だらけの素数出力命令
タイトルにあるように「ドキッ」とはしなくとも、動悸が止まら
ない人はいるのではないかと思います。
ここでは、その処理内容の詳細は解説しませんが、「なぜ訳の分
からないコマンド列になってしまったか」を紐解いてみます。
eval eval ''n='''{1..'$(dc -e 1000vp)'}''' eval eval eval
echo '''''''$
(( '''''''$n'''''''
*''''''''{2..$((
1000/n))}''''''''))
''''''';'' |
tr ' ' n | sort -n | uniq -u
ドキッ!”\”だらけの素数出力命令
この長文ワンライナーの大半を占める”eval”コマンドと”\”(バッ
クスラッシュ)、” ’ ”(シングルクォート)の正体を見てみます。
”eval”コマンドは、引数に渡されたコマンド列を実行してくれる
便利なものですが、以下のように意図せず変化したり消えてしま
うものがあります。
● 処理を行う際に消えてしまう(例:クォート、エスケープ)
● 想定外の展開処理を行われてしまう(例:*)
ドキッ!”\”だらけの素数出力命令
”eval”に弱い文字への対策(いたちごっこ)について説明します。
1.まず、”echo”でセミコロンを表示してみます。
2.これを”eval”で処理すると…セミコロンが表示されません
これは、セミコロンをくくっていた” ’ ”が”eval”内で消えてし
まったために、”echo”で渡していたセミコロンがコマンドの区
切り文字になってしまったためです。
$ echo ';’
;
$ eval echo ';’
ドキッ!”\”だらけの素数出力命令
3.再びセミコロンを表示するには、” ’ ”で括りなおしてあげる必
要があるのですが、そのままだと返り討ちにあってしまうの
で、エスケープ文字で補強してあげる必要があります。
4.さらに”eval”を追加すると、やはりセミコロンが表示されなく
なるので、さらなる補強が必要となります。
この時のエスケープ文字の数は、次の要領で求められます。
《内側のエスケープ文字の数》x2+1
$ eval echo ’';’’
$ eval eval echo ’’';’’’
ドキッ!”\”だらけの素数出力命令
5.”eval”3回重ねると、下記の様になります。
6.“eval”を4回重ねると、下記の様になります。
もはやセミコロンを表示するという本来の目的が見えません。
$ eval eval echo ’’’';’’’’
$ eval eval eval eval
echo '’’’';’’’’
'
ドキッ!”\”だらけの素数出力命令
その他の部分についての解説です(もはや「おまけ」)
これは、”dc”コマンド内で直に指定するオプション(-e)の設定と、
「1000の平方根(1000v)」「結果を改行付きで表示(p)」を組み合
わせたものです。1000の平方根は整数レベルでは31となります。
この値が変数nに代入され、先のエスケープ文字だらけの"eval”処
理を複数回繰り返す形に展開され、最終的に1~1000の間にある
素数が表示されるのです。
$ dc -e 1000vp
ドキッ!”\”だらけの素数出力命令
「2~1000の範囲に存在する素数を表示」するこの謎のコードに
関する解説は、以下のYouTube動画で詳しく解説されています。
● 第38回シェル芸勉強会 LT(1/3)
「鳥海さんのバックスラッシュeval素数ライブコーディング」
https://www.youtube.com/watch?v=DlokiFQRpk8
うねうね、うねうね…
いわゆるフラクタル図形による空間補充曲線の描画ルールをシェ
ル芸で作成します。処理方法としては、先ほどの「素数を出力」
するものと傾向は似ています。
本来は数学的な知識などが要求される分野ではありますが、ここ
では肩の力を抜いて「幾何学的な模様を楽しむ」ことにとどめて
ください。
※「怪物曲線」と呼ぶ場合もあるようです(正式名ではない?)。
うねうね、うねうね…
これは Python の Turtle Graphics ライブラリによる描画機能で
用いるスクリプトをシェル芸で生成するものです。再帰的に実行
される回数をもとにサイズや角度が自動調整がおこなわれます。
主に以下の命令を用いています。
位置決め …… setpos(x,y)
方向転換 …… lt(angle) , rt(angle)
直線描画 …… fd(length)
うねうね、うねうね…
ここでは、以下のバリエーションの描画を行うプログラムと描画
状況の実演を紹介します。
● ヒルベルト曲線
● シェルピンスキー曲線
● ゴスパーの流蛇(N=7, 13, 19)
● シェルピンスキーのガスケット
暗記と詠唱には不向きなもの
には、それぞれのコードを元
にQRコード化した画像を掲載
しています。
※QRコードは株式会社デンソーウェー
ブの登録商標です。
うねうね、うねうね…
ヒルベルト曲線(1~6次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
うねうね、うねうね…
シェルピンスキー曲線(1~6次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
うねうね、うねうね…
ゴスパーの流蛇(N=7/1~4次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
うねうね、うねうね…
ゴスパーの流蛇(N=13/1~3次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
うねうね、うねうね…
ゴスパーの流蛇(N=19/1~3次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
うねうね、うねうね…
シェルピンスキーのガスケット
(1~6次)
当日はコマンド( QR⇒ コード)による描画実演を行っています。
【実践】はじめよう、シェル芸
もうxxx回寝るとお正月!
【問題】
今日は5月23日です。少々早いですが「もういくつ寝る
とお正月」をお正月までの日数に置き換えて表示してく
ださい。
もうxxxつ寝るとお正月
もうxxx回寝るとお正月!
5月23日からお正月までの日数を考える問題です。
“date”コマンドには「その年の何日目」、システム上の
基準日(一般的に1970年1月1日)からの「秒数」を出力
できますので、2020年5月23日から2021年1月1日まで
の日数を考えてみます。
もうxxx回寝るとお正月!
《「その年の何日目」》で考える
「(その年の)何日目か」は”date”コマンドのフォーマッ
ト指定”%j”で得られます。が、年が変わるとリセットさ
れるため、直接2021年1月1日が使えませんので注意が
必要です。その代替として2020年12月31日を使って引
き算ののち、差分である1を加算します。
$ echo $(( $(date --date “20201231” +%j) - $(date --date
”20200523” +%j) + 1 ))
もうxxx回寝るとお正月!
《システム上の基準日からの「秒数」で考える》
単純に2021年1月1日を指す値から2020年5月23日を指
す値の差を計算します。単純な引き算なので、基準日を
気にする必要はありません。また、ここで得られる値は
あくまで秒数なので、これを日数に直すために86400
(24x60x60)で割ります(四則演算の優先順位に注意)。
$ echo $(( $(date --date “20201231” +%s) - $(date --date
”20200523” +%s) / 86400 ))
もうxxx回寝るとお正月!
《あれ?1日たりない?》
得られた結果を確認のために、次のコマンドを実行する
と、なぜか今年の大晦日になった人はいませんか?
これは、今日の日付の値を計算する際に引数を省略した
り、”today”や”now”を指定したときに遭遇します。
$ date --date “+xxx days”
Thu Dec 31 00:00:00 JST 2020
もうxxx回寝るとお正月!
《「1日たりない」を回避するには?》
先に紹介した解答例には書きましたが、日数計算を行う
場合は、時刻を同じにする(日付を明示的に指定すると
00:00です)のが確実です。
ちなみに、1日足りなくなった原因は、整数計算による
「切り捨て」に起因するものです。
$ date --date “2020/5/23”
Sat May 23 00:00:00 JST 2020
指定した情報の行を取り出す
【問題】
/etc/services から、TCPの80番ポートを使うサービス
の行だけ抽出してください。できる人はなるべく多くの
方法を考えてみましょう。
http 80/tcp www # WorldWideWeb HTTP
指定した情報の行を取り出す
/etc/services には、既知のサービス名と利用ポート番
号が登録されています。今回は”TCP80番”と指定された
ので、”80/tcp”で”grep”に掛ければ…という具合に一筋
縄ではいきません。
$ grep "80/tcp" /etc/services
http 80/tcp www # WorldWideWeb HTTP
socks 1080/tcp # socks proxy server
http-alt8080/tcp webcache # WWW caching service
amanda 10080/tcp # amanda backup services
canna 5680/tcp # cannaserver
指定した情報の行を取り出す
”grep”でチャレンジする場合は、直前にある空白文字を
条件に加えることで余計な出力を回避できます。
また、”awk”なら2項目めを取り出して比較可能です。
その他のコマンドでも解答可能な柔軟な問題ですので、
ぜひ他の解答例も考えてみてください。
$ grep "s80/tcp" /etc/services
$ cat /etc/services | awk -F' ' '{if($2 == "80/tcp"){print}}'
FizzBuzz…それ、ワンライナーで!
【問題】
連続する整数を表示し、それらをもとに3で割り切れる
ときは”fizz”を、5で割り切れるときは”buzz”をそれぞれ
表示してください。
1 6 fizz 11
2 7 12 fizz
3 fizz 8 13
4 9 fizz 14
5 buzz 10 buzz 15 fizz buzz
FizzBuzz…それ、ワンライナーで!
いわゆる「FizzBuzz」問題です。
3ないし5で割り切れるときに実行される条件分岐を設置
するのが簡単ですが、より多くのスマートな方法もある
ようです。
《解答例は、次頁に掲載します。》
FizzBuzz…それ、ワンライナーで!
条件分岐でやる方法
sedの条件付き置換を使う方法
上記に限らず、多くの解法がある問題ですので、別の解
き方を考えるのもまた一興です。
seq 15 | sed '0~3s/$/ Fizz/' | sed '0~5s/$/ Buzz/'
for i in $(seq 15); do echo -n $i; [ $(($i % 3)) -eq 0 ] &&
echo -n “ fizz”; [ $(($i % 5)) -eq 0 ] && echo -n " buzz";
echo; done
郵便番号簿から始めるデータ抽出
【問題】
南島原市内の合併前の町名を、長崎県の郵便番号簿から
取り出してください。データは下記から取得できます。
https://www.post.japanpost.jp/zipcode/dl/kogaki/zip/42nagasa.zip
【ヒント】
nkfなどで読みやすい形に変換すると楽に解けるかもし
れません(中身のエンコードはShiftJISのため)。
郵便番号簿から始めるデータ抽出
広く配布・普及しているデータを弄って遊ぶ(?)問題で
す。この手のデータ処理問題は、いわゆるビッグデータ
をシェル上で取り扱う上でも有用です。
南島原市内の合併前の町名は、いずれも「南島原市」の
次に表記されている(ソース:Wikipedia)とのことです
ので、比較的楽に解くことができるかもしれません。
では、今回利用したデータを見ていきましょう。
郵便番号簿から始めるデータ抽出
ダウンロードした”42nagasa.zip”を展開すると、
”42NAGASA.CSV”が保存されます。
拡張子が示す通りCSVファイルなので、先頭の数行を表
示してみると…なるほど、文字化けで分かりません。
$ head -n 2 42NAGASA.CSV
42201,"850 ","8500000","Ŷ޻���","Ŷ޻��","�� �����Ų�ƹ ‫�ޱ‬","���
茧","�����s","�ȉ�� f�Ɍ ‫��ڂ‬ ��Ȃ ꍇ",0,0,0,0,0,0
42201,"850 ","8500922","Ŷ޻���","Ŷ޻��","������","���
茧","�����s","������",0,0,0,0,0,0
郵便番号簿から始めるデータ抽出
この文字化けは、ShiftJISでエンコードに由来しますの
で、”nkf”コマンドを通せば、UNIX系の環境でも問題な
く表示できます。
また、ここで使えるのは漢字住所のうち8番目(市町村)・
9番目(以降の住所)であることもわかります。
$ head -n 1 42NAGASA.CSV | nkf
42201,"850 ","8500000","ナガサキケン","ナガサキシ","イカニケイサイガナ
イバアイ","長崎県","長崎市","以下に掲載がない場合",0,0,0,0,0,0
42201,"850 ","8500922","ナガサキケン","ナガサキシ","アイオイマチ","長
崎県","長崎市","相生町",0,0,0,0,0,0
郵便番号簿から始めるデータ抽出
「南島原」で絞り込んむととも
に、第9フィールドを取り出す
と、合併前の町名と町名(大字)が
表示されます。
"以下に掲載がない場合"
"有家町石田"
"有家町大苑"
"有家町尾上"
"有家町蒲河"
"有家町久保"
"有家町小川"
"有家町中須川"
"有家町原尾"
"有家町山川"
   :
 (以下略)
$ cat 42NAGASA.CSV | nkf | grep "南島原" |
awk -F, '{print $9}'
郵便番号簿から始めるデータ抽出
今回必要なデータは「○○町」な
ので、「町」以降の文字列を除去
してしまいます。
"以下に掲載がない場合"
"有家町"
"有家町"
"有家町"
"有家町"
"有家町"
"有家町"
"有家町"
"有家町"
"有家町"
   :
 (以下略)
$ cat 42NAGASA.CSV | nkf | grep "南島原" |
awk -F, '{print $9}' | tr -d '"'|sed -e
's/町.*/町/'
郵便番号簿から始めるデータ抽出
「○○町」で出力を止めたことに
より発生する重複を除去します。
"以下に掲載がない場合"
"有家町"
"加津佐町”
“口之津町”
“深江町”
“西有家町”
“南有馬町”
“布津町”
“北有馬町”
“有家町"
$ cat 42NAGASA.CSV | nkf | grep "南島原" |
awk -F, '{print $9}' | tr -d '"'|sed -e
's/町.*/町/' | sort | uniq
郵便番号簿から始めるデータ抽出
最後に「以下に掲載がない場合」
を除去して完成です。
"有家町"
"加津佐町”
“口之津町”
“深江町”
“西有家町”
“南有馬町”
“布津町”
“北有馬町”
“有家町"
$ cat 42NAGASA.CSV | nkf | grep "南島原" |
awk -F, '{print $9}' | tr -d '"'|sed -e
's/町.*/町/' -e '/以下/d' | sort | uniq
逆向きアスキーアートを作る
【問題】
以下のcowsayコマンドで表示されるキャラクタの向き
を変えてください。時間に余裕のある人は、ほかのキャ
ラクターでも挑戦してみてください(キャラクタデータ
は、”/usr/share/cousay/cows”配下にあります)。
$ cowsay -f cower.cow 南島原オープンキャンプ2020オンライン
逆向きアスキーアートを作る
ベースとなるcowsayの出
力です。
______________________________________
< 南島原オープンキャンプ2020オンライン >
--------------------------------------


,__, | |
(oo)| |___
(__)| | )_
| |_w | 
| | || *
Cower....
$ cowsay -f cower.cow 南島原オープンキャンプ2020オンライン
逆向きアスキーアートを作る
「cowsayの出力を逆向き
にすればいいんじゃね?」
と思ったあなたは甘い!
結果はこの通り…。
ダメだこりゃ…ですね。
$ cowsay -f cower.cow 南島原オープンキャンプ2020オンライン | rev
______________________________________
> ンイランオ0202プンャキンプーオ原島南 <
--------------------------------------


| | ,__,
___| |)oo(
_) | |)__(
 | w_| |
* || | |
....rewoC
逆向きアスキーアートを作る
反転処理の方針です…。
l.1~3 反転せずに右寄せ
l.4~11 崩さずに反転
l.12 そのまま
《理想形を出力するためのコマンド群は、のちほど…》
______________________________________
< 南島原オープンキャンプ2020オンライン >
--------------------------------------
/
/
| | ,__,
___| |/(oo)
_/( | |/(__)
/ | w_| |
* || | |
Cower....
逆向きアスキーアートを作る
空白を"@”に、”\”を"$”
に変換します(崩れ対策)。
行頭にフラグ(“#”(l.1~
3)、”%”(l.4~11))を付加
します。
$ cowsay -f cower.cow "南島原オープンキャンプ2020オンライン" | sed -e
's//$/g;s/ /@/g' -e '1 s/$/@/;3 s/$/@/;1,3 s/^/#/;4,11 s/^/%/'
#@______________________________________@
#<@南島原オープンキャンプ2020オンライン@>
#@--------------------------------------@
%@@@@@$
%@@@@@@$
%@@@@@@@@,__,@|@@@@|@
%@@@@@@@@(oo)$|@@@@|___
%@@@@@@@@(__)$|@@@@|@@@)$_
%@@@@@@@@@@@@@|@@@@|_w@|@@$
%@@@@@@@@@@@@@|@@@@|@@||@@@*
%
@@@@@@@@@@@@@Cower....
逆向きアスキーアートを作る
アスキーアートの幅に合わ
せたときに空白になる箇所
も、"@”で埋めて行の長さ
を調整し、反転に備えま
す。
$ cowsay -f cower.cow "南島原オープンキャンプ2020オンライン" | sed -e
's//$/g;s/ /@/g' -e '1 s/$/@/;3 s/$/@/;1,3 s/^/#/;4,11 s/^/%/' | while
read line;do [[ $line =~ ^# ]] && line=$(printf "%30sn" $line|sed -e
'y/ /@/'); line=$(printf "%-30sn" $line |sed -e 'y/ /@/');echo $line;
done)
#@______________________________________@
#<@南島原オープンキャンプ2020オンライン@>
#@--------------------------------------@
%@@@@@$@@@@@@@@@@@@@@@@@@@@@@@
%@@@@@@$@@@@@@@@@@@@@@@@@@@@@@
%@@@@@@@@,__,@|@@@@|@@@@@@@@@@
%@@@@@@@@(oo)$|@@@@|___@@@@@@@
%@@@@@@@@(__)$|@@@@|@@@)$_@@@@
%@@@@@@@@@@@@@|@@@@|_w@|@@$@@@
%@@@@@@@@@@@@@|@@@@|@@||@@@*@@
%@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@@@@@@@@@@@@@Cower....@@@@@@@@
逆向きアスキーアートを作る
”%”が先頭にある行(l.4~
11)を”rev”で反転しなが
ら出力します。
cowsay -f cower.cow "南島原オープンキャンプ2020オンライン" | sed -e
's//$/g;s/ /@/g' -e '1 s/$/@/;3 s/$/@/;1,3 s/^/#/;4,11 s/^/%/' | while
read line;do [[ $line =~ ^# ]] && line=$(printf "%30sn" $line|sed -e
'y/ /@/'); line=$(printf "%-30sn" $line |sed -e 'y/ /@/');[[ $line =~ ^
% ]] && echo $line|rev ||echo $line; done
#@______________________________________@
#<@南島原オープンキャンプ2020オンライン@>
#@--------------------------------------@
@@@@@@@@@@@@@@@@@@@@@@@$@@@@@%
@@@@@@@@@@@@@@@@@@@@@@$@@@@@@%
@@@@@@@@@@|@@@@|@,__,@@@@@@@@%
@@@@@@@___|@@@@|$)oo(@@@@@@@@%
@@@@_$)@@@|@@@@|$)__(@@@@@@@@%
@@@$@@|@w_|@@@@|@@@@@@@@@@@@@%
@@*@@@||@@|@@@@|@@@@@@@@@@@@@%
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@%
@@@@@@@@@@@@@Cower....@@@@@@@@
逆向きアスキーアートを作る
逆向きにしたときに変にな
る文字、型崩れ防止のため
に一時的に置き換えた文字
を元に戻して完成です。
(cowsay -f cower.cow "南島原オープンキャンプ2020オンライン" | sed -e
's//$/g;s/ /@/g' -e '1 s/$/@/;3 s/$/@/;1,3 s/^/#/;4,11 s/^/%/' | while
read line; do [[ $line =~ ^# ]] && line=$(printf "%30sn" $line | sed -e
'y/ /@/'); line=$(printf "%-30sn" $line | sed -e 'y/ /@/'); [[ $line =~
^% ]] && echo $line | rev || echo $line; done) | sed -e 'y/$@()// )(/;s/%
$//g;s/#/ /'
______________________________________
< 南島原オープンキャンプ2020オンライン >
--------------------------------------
/
/
| | ,__,
___| |/(oo)
_/( | |/(__)
/ | w_| |
* || | |
Cower....
逆向きアスキーアートを作る
問題の解説で使用したコマンド群を詠唱するためのQR
コードは、それぞれ以下のようになっています。
Step1
前方の崩れ対策
Step2
後方の崩れ対策
Step3
アスキーアート
の反転
Step4
文字置換とダミー
文字の除去(完成)
Q&A
ご参加いただき
ありがとうございました。

More Related Content

What's hot

クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
mametter
 
Perlで伝統芸能
Perlで伝統芸能Perlで伝統芸能
Perlで伝統芸能
hitode909
 

What's hot (9)

20130824 第六回チャンピオンシップシェル芸ランナー勉強会 in LLまつり
20130824 第六回チャンピオンシップシェル芸ランナー勉強会 in LLまつり20130824 第六回チャンピオンシップシェル芸ランナー勉強会 in LLまつり
20130824 第六回チャンピオンシップシェル芸ランナー勉強会 in LLまつり
 
Uspstudy20121208qonly
Uspstudy20121208qonlyUspstudy20121208qonly
Uspstudy20121208qonly
 
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
クックパッド春の超絶技巧パンまつり 超絶技巧プログラミング編 資料
 
[JANOG38]Peeringの見える化を自力でやってみた。
[JANOG38]Peeringの見える化を自力でやってみた。[JANOG38]Peeringの見える化を自力でやってみた。
[JANOG38]Peeringの見える化を自力でやってみた。
 
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
Ruby を用いた超絶技巧プログラミング(夏のプログラミングシンポジウム 2012)
 
再帰的 正規表現JSON Validator
再帰的 正規表現JSON Validator再帰的 正規表現JSON Validator
再帰的 正規表現JSON Validator
 
Perlで伝統芸能
Perlで伝統芸能Perlで伝統芸能
Perlで伝統芸能
 
wakuwaku Scala ~Scala入門勉強会~ 資料
wakuwaku Scala ~Scala入門勉強会~ 資料wakuwaku Scala ~Scala入門勉強会~ 資料
wakuwaku Scala ~Scala入門勉強会~ 資料
 
怪物曲線2 - evalの復習
怪物曲線2 - evalの復習怪物曲線2 - evalの復習
怪物曲線2 - evalの復習
 

Similar to 「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online

詳説ぺちぺち
詳説ぺちぺち詳説ぺちぺち
詳説ぺちぺち
do_aki
 
Usp友の会勉強会、ジャクソン構造図の巻(前編)
Usp友の会勉強会、ジャクソン構造図の巻(前編)Usp友の会勉強会、ジャクソン構造図の巻(前編)
Usp友の会勉強会、ジャクソン構造図の巻(前編)
umidori
 

Similar to 「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online (15)

色々なダイクストラ高速化
色々なダイクストラ高速化色々なダイクストラ高速化
色々なダイクストラ高速化
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 
Gorinphp0729
Gorinphp0729Gorinphp0729
Gorinphp0729
 
詳説ぺちぺち
詳説ぺちぺち詳説ぺちぺち
詳説ぺちぺち
 
Jpoug 20120721
Jpoug 20120721Jpoug 20120721
Jpoug 20120721
 
Usp友の会勉強会、ジャクソン構造図の巻(前編)
Usp友の会勉強会、ジャクソン構造図の巻(前編)Usp友の会勉強会、ジャクソン構造図の巻(前編)
Usp友の会勉強会、ジャクソン構造図の巻(前編)
 
STC-OC2019_1st201906
STC-OC2019_1st201906STC-OC2019_1st201906
STC-OC2019_1st201906
 
What is Metasepi?
What is Metasepi?What is Metasepi?
What is Metasepi?
 
勉強会課題①
勉強会課題①勉強会課題①
勉強会課題①
 
拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化拡張ライブラリ作成による高速化
拡張ライブラリ作成による高速化
 
OpenGLと行列
OpenGLと行列OpenGLと行列
OpenGLと行列
 
OpenGLと行列
OpenGLと行列OpenGLと行列
OpenGLと行列
 
WUPC2012
WUPC2012WUPC2012
WUPC2012
 
JavaScriptの正規表現
JavaScriptの正規表現JavaScriptの正規表現
JavaScriptの正規表現
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 

「はじめよう、シェル芸」オープンキャンプin南島原2020/OpenCamp in Minami-shimabara online