jus共催第27回シェル芸勉強会のリンク集

Pocket
LINEで送る

2017年2月11日(土曜日)にさくらインターネットさんにて開催しました。日本UNIXユーザ会(jus)さんとの共催でした。

sedに絞って機能を使ってみる出題にしたのでいつもより勉強会っぽい勉強会になりました。最後の三問が急に難しくなって「ハシゴを外された」との声もありましたが・・・。

酸化参加された皆様、会場を提供いただいたさくらインターネットさん横田さん、午前の部の講師の鳥海さん石井さん、ストリーミングを担当された宮川さん、濃いLT勢の皆様、jusのりゅうちさん、Twitter勢の皆様、そしてサテライト会場の皆様、ありがとうございました。

問題

 

録画

サテライト会場

まとめ

ブログ等

多すぎるので今回からまとめのところからのリンクで代用させていただきます・・・

番外編

翌日の別の勉強会で危険シェル芸が炸裂したそうです・・・

Vimシェル芸の予感・・・

Pocket
LINEで送る

【問題と解答】第27回sedこわいシェル芸勉強会

Pocket
LINEで送る

問題のみのページはこちら。

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.27

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

イントロ

環境

対象とするsedはGNU sedだけに絞っています。解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールの上、gsedをつかいましょう。BSD系の人は玄人なので各自対応のこと。

Q1

次のechoの出力について、偶数番目の文字だけ大文字にしてください。できたら、奇数番目の文字だけ大文字にしてください。

$ echo abcdefghijklmn

解答

###偶数番目を大文字に###
$ echo abcdefghijklmn | sed 's/\(.\)\(.\)/\1\U\2/g'
aBcDeFgHiJkLmN
###奇数番目を大文字に###
$ echo abcdefghijklmn | sed 's/\(.\)\(.\)/\U\1\L\2/g'
AbCdEfGhIjKlMn
###-rを使うと多少スッキリする###
$ echo abcdefghijklmn | sed -r 's/(.)(.)/\U\1\L\2/g'
AbCdEfGhIjKlMn

Q2

seq 1 100から始めてsedだけでFizzBuzzをやってみましょう。

解答

$ seq 1 100 | sed '0~3s/.*/Fizz/;0~5s/$/Buzz/' |
 sed 's/[0-9]*B/B/' | xargs

Q3

次の出力について、3行目を7行目の下に移動してください。

$ seq 1 10

解答

hで3行目をホールドスペースに突っ込み、Gでパターンスペースに戻します。

$ seq 1 10 | sed '3h;3d;7G'

Q4

次のコードのmainとahoの位置を入れ替えてください。

$ cat aho.cc 
#include <iostream>
using namespace std;

int main(int argc, char const* argv[])
{
	aho();
	return 0;
}

void aho(void)
{
	cout << "aho" << endl;
}

解答

mainの部分をホールドスペースに入れる→消す→ファイルの一番後ろでホールドスペースを吐き出すという流れになります。

$ cat aho.cc | sed '/int/,/}/H;/int/,/}/d;$G'
#include <iostream>
using namespace std;


void aho(void)
{
	cout << "aho" << endl;
}

int main(int argc, char const* argv[])
{
	aho();
	return 0;
}
###{}でまとめる###
$ cat aho.cc | sed '/int/,/}/{H;d};$G'
###もうちょっと厳密なやつ###
$ cat aho.cc | sed '/ main(/,/^}/{H;d};$G'
###そのままコンパイルして実行###
$ cat aho.cc | sed '/int/,/}/H;/int/,/}/d;$G' |
 g++ -x c++ - && ./a.out
aho

Q5

seq 1 10 | から始めて次のような出力を作ってください。

2
1
4
3
6
5
8
7
10
9

解答

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

Q6

echo 1から始めて次のような出力を作ってください。

1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111

解答

ラベルを使います。

$ echo 1 | sed ':LOOP p;s/./&&/;b LOOP' | head
1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111
###分岐を使う###
$ echo 1 | sed ':LOOP p;s/./&&/;/1\{10\}/!b LOOP'

Q7

aというファイルをtouch等で作り、次の縛りでa1, a2, a3, …, a10というファイルをaからコピーして作ってください。縛り1と縛り2を独立した別々の問題として解き、その後縛り1,2を両方満たす解を考えてみましょう。

  • 縛り1: 使うコマンドはseq、cp、sedだけ
  • 縛り2: ワンライナー中で数字を使わない

解答

###縛り1###
$ touch a
$ seq 1 10 | sed 's/./cp a a&/e'
$ ls a a? a10
a  a1  a10  a2  a3  a4  a5  a6  a7  a8  a9
###縛り2###
$ yes | sed -n '=' | head | sed 's/./cp a a&/e'
###両方###
$ sed ':a ;p;s/./&&/;/........../!b a' <<< y |
 sed -n = | sed 's/^/cp a a/e'
###(おまけ)ファイルaをsedで作る###
$ sed 'w a' <<< "abc"
abc
$ cat a
abc

Q8

echo 1 | から始めて、あとはsedだけで次のような出力を得てください。

1
11
111
1111
11111
11111
1111
111
11
1

解答

$ echo 1 | sed ':LOOP p;s/./&&/;/1\{5\}/!b LOOP' | sed 'p;1!G;h;$!d'
1
11
111
1111
11111
11111
1111
111
11
1
Pocket
LINEで送る

【問題のみ】第27回sedこわいシェル芸勉強会

Pocket
LINEで送る

解答例はこちら

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.27

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

イントロ

環境

対象とするsedはGNU sedだけに絞っています。解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールの上、gsedをつかいましょう。GSD系の人は玄人なので各自対応のこと。

Q1

次のechoの出力について、偶数番目の文字だけ大文字にしてください。できたら、奇数番目の文字だけ大文字にしてください。

$ echo abcdefghijklmn

Q2

seq 1 100から始めてsedだけでFizzBuzzをやってみましょう。

Q3

次の出力について、3行目を7行目の下に移動してください。

$ seq 1 10

Q4

次のコードのmainとahoの位置を入れ替えてください。

$ cat aho.cc 
#include <iostream>
using namespace std;

int main(int argc, char const* argv[])
{
	aho();
	return 0;
}

void aho(void)
{
	cout << "aho" << endl;
}

Q5

seq 1 10 | から始めて次のような出力を作ってください。

2
1
4
3
6
5
8
7
10
9

Q6

echo 1から始めて次のような出力を作ってください。

1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111

Q7

aというファイルをtouch等で作り、次の縛りでa1, a2, a3, …, a10というファイルをaからコピーして作ってください。縛り1と縛り2を独立した別々の問題として解き、その後縛り1,2を両方満たす解を考えてみましょう。

  • 縛り1: 使うコマンドはseq、cp、sedだけ
  • 縛り2: ワンライナー中で数字を使わない

Q8

echo 1 | から始めて、あとはsedだけで次のような出力を得てください。

1
11
111
1111
11111
11111
1111
111
11
1
Pocket
LINEで送る

【問題のみ】第26回シェル芸勉強会及びエクシェル芸勉強会

Pocket
LINEで送る

解答はコチラ

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.26

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

シェル芸を行うのはUbuntu Linux 16.04です。確認はMacのExcelやWord, PowerPointで行いました。今回は特にワンライナーにこだわる必要はありません。シェルスクリプトにしても構いません。もちろん、一般解にこだわる必要もありません。

イントロ

第26回シェル芸勉強会及びエクシェル芸勉強会

Q1

.xlsxや.docx、.pptxファイルはzipファイルです。リポジトリの中のxlsx,docx,pptxを展開し、中にどんなファイルがあるか見て、再び戻して再び.xlsxファイルとして開いてみてください。

Q2

20141019OSC_LT.pptxのスライドに何回「危険」という単語が出てくるか数えてください。画像になっているものは除きます。

Q3

20141019OSC_LT.pptxのスライドから画像を抽出して、一つのディレクトリにまとめてzipで固めてください。

Q4

20141019OSC_LT.pptxのスライドの7ページ目のテキストをスクレイピングしましょう。以下が出力の例です。

戦果(?)
初日だけで見知らぬ方のマシン3台轟沈
その他自爆者多数
Docker上で試したらホストマシン沈黙の報告
自分の本がサイト経由で1冊だけ売れた
フォロワーが1人減った
(以下、フッタ等の文字列が混ざっても可とします)

Q5

graph.xlsxの2列の数字を抜き出して端末にSSV形式のデータ(CSVのカンマがスペースになったもの)、あるいはセルの番号と値のリストとして抜き出してください。

Q6

hanshin.xlsxのシートについてQ2と同様SSV形式か、セルの番号と値のリストとして端末上に出力してください。日付のセルについては何を出力しても良いことにします。

Q7

certificate.docxファイルを開いて確認し、人の名前が入るところに好きな名前を入れてみましょう。

Q8

Q7を応用し、次のリストlist.txtで、複数の表彰状を作ってみましょう。

$ cat list.txt 
シェル芸おじさん
シェル芸野郎
変態シェル芸豚野郎
Pocket
LINEで送る

SHELQ: 怪しいシェル芸キュレーションサイト

Pocket
LINEで送る

この記事はShell Script Advent Calendar 2016 18日目の記事です。

本記事の趣旨は、今年を中心にTwitterやシェル芸勉強会上で出たこわいワンライナーを、巷にあふれるクソバイラル的なランキング形式でお届けしようというものです。人さまのワンライナーを紹介していきます。普段、自分のブログでは人のふんどしでほんだしをとる1) ふんどしを脱ぐと立派な鰹節が出現するイメージの下ネタです。ようなことはなるべくしないことにしてますが、毎年謎に盛り上がるShell Script Advent Calendarに便乗してしれっとやります。あと、先日せっかくこんなことを書いたのにまるで自分で守ってないのは、やさぐれているからです。ご了承ください。

ということで、私、上田マリ(シェルガポール在住)の「シェル芸キュレーション」をお楽しみください。

今、私は、シェルガポールからのリモートシェル芸で、いかにshelqとシェル芸ヴェンキョウカイを成長させていくかしか考えていません。この新たな挑戦と新しい働き方へのトライに、シェルシェルシェルシェル、核シェルターですね。 —上田マリ

すみません!ほんとすみません!2) かなりイキってるインタビューである https://m.newspicks.com/news/651502/body/?sentlog を参考にさせていただきました。

Ubuntu 16.04 LTSのGUI環境で、必要なものをインストールした上で動作を確認しています。しかし、何が起きても責任は負えません。

第10位 (2016年2月・微妙に危険)

$ touch + ; echo 2 * 3 | bc
5

まずは第10位。「第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会」の午前の部で鳥海さんによって誘発された「こんなミス誰もしないだろシェル芸」です。

上記のような計算間違いは「ディレクトリの中に『+』と言う名前のファイルがあり、そしてbcを使う時にアスタリスクのクオートを忘れると、アスタリスクがファイルのリストに変換(+だけなので+に変換)されて『2 + 3』がbcに渡る」という、ありがちな状況でよく起こります。ありがちではありません。

このバカバカしい計算間違い体験をどうしてもしたい方は、次のようにシェルとよろしくやっててください。

mery@welq:~$ mkdir iemo
mery@welq:~$ cd !$
cd hoge
mery@welq:~/iemo$ touch +
mery@welq:~/iemo$ echo 2 * 3 | bc
5

以上、第10位でした。

第9位(2015年10月・ちょっと危険

$ echo {000000000..9999999999}

第9位は「100億個の数字をメモリに書くまでbashとお前を家に帰さない危険シェル芸」です。マイナンバーシェル芸事件3) マイナンバーに抜けがないか、みんなで仲良く襲撃検証した事件。の際、とりあえず数字を全部列挙しようとしている最中に飛び出した危険なワンライナーです。

ナニがドーなるか説明しておきます。bashは

spotlight@never:~$ echo {0..9}
0 1 2 3 4 5 6 7 8 9

というふうに、連番を略記して入力すると展開して、コマンド(この場合はecho)に渡してくれる機能があります。コマンドに展開したものを引数として渡すには・・・全部メモリの上で展開する必要があります。これを踏まえて、もう一度9位のコマンドを見てください。bashが可哀想に見えます。

このときは、bashだけでなく、次の方々が犠牲になりました。尊い。

尊い。

第8位 (2016年10月)(安全・迷惑)

$ echo 響け!ユーフォニアム | sed ':a;p;s/\(.\)\(.*\)/\2\1/;/^ム/!ba'
響け!ユーフォニアム
け!ユーフォニアム響
!ユーフォニアム響け
ユーフォニアム響け!
ーフォニアム響け!ユ
フォニアム響け!ユー
ォニアム響け!ユーフ
ニアム響け!ユーフォ
アム響け!ユーフォニ
ム響け!ユーフォニア

第8位は、@ebanさんの「響け!ユーフォニアム10段逆スライド方式シェル芸」です。ある日、上の出力のように1文字ずつずらして「響け!ユーフォニアム」という文字列を出力するだけの不毛なパズルがTwitter上で暇な人たちによって流行ったのですが、みんながワイワイ長いワンライナーを捻り出している時にしれっと氏が出したものです。

一応、ちゃんと解説をしておくと、これはsed(GNU sed)のbコマンドを用いたものです。sedの部分をsedのスクリプトファイルにしてコメントを入れると、次のようになります。

curazy@grape:~$ cat ufo.sed 
#!/bin/sed -f
                   
#aというラベルをつける。「b a」でここに戻る
:a  

#1行プリント
p

#一番最初の字を後ろにくっつける
s/\(.\)\(.*\)/\2\1/

#ムで始まらなければラベルaに戻る
/^ム/!b a

このスクリプトに「響け!ユーフォニアム」という文字列を入れると、頭の文字が「ム」になるまで同じ行に対してp(プリント)が実行されるので、上記のような出力が得られます。

実行は次のように行いましょう。

takagi@buzznews:~$ chmod +x ./ufo.sed
takagi@buzznews:~$ echo 響け!ユーフォニアム | ./ufo.sed 
響け!ユーフォニアム
け!ユーフォニアム響
!ユーフォニアム響け
ユーフォニアム響け!
ーフォニアム響け!ユ
フォニアム響け!ユー
ォニアム響け!ユーフ
ニアム響け!ユーフォ
アム響け!ユーフォニ
ム響け!ユーフォニア

ちなみに、やり出しっぺの人は

だそうです。代わりに謝っておきます。私も見たことも食べたこともありません。ファンの人たちには本当に迷惑な話です。

第7位 (2016年9月・安全)

$ banner --help

どうなるか?こうなります。

以上、ぐれさんの「コマンドに馬鹿にされるシェル芸」でした。

第6位(2014年8月他、破壊実績多数・試すな危険

$ : () { : | : & } ; : 

第6位は、すこしリリース(?)から時間が経ってしまったのでランクダウンしましたが、未だに存在感抜群のforkbombです。これをシェルに打ち込むと、なにも対策を立てる間も無くOSが死にます。

この入力の意味は「:という名前の関数を定義します。その関数は、自分自身をパイプで2つつないだものをバックグラウンドプロセスで実行するというものです。:を定義したら、さっそく実行します。」というものなので、:がひとつ実行するごとに、別の:が起動して、それらが再び:を2つ起動して・・・」と倍々になってすぐプロセスで一杯になってOSが死にます。どんどんプロセスを使うので他のコマンドも起動できず、大抵の場合シャットダウンもうまくいきません。

Dockerなら大丈夫だろうと試したらホストまで死んだという報告もあるので、試すなよ!絶対試すなよ!

第5位(2014年9月・ある意味危険

$ env x='() { :;}; echo vulnerable' bash -c 'echo this is a test'
vulnerable
this is a test

第5位は、これもちょっと古いのでランクを落としてしまった「Shellshock調査用ワンライナー」です。Shellshockは、「関数の定義を変数に代入しようとすると、関数の後ろに書いたコマンドが実行できてしまう。」というbashのバグ(と、その後の騒動)を指します。

これだけなら「ふーん」という感じですが、CGIでbashが立ち上がるようになっていると話は別です。webサーバがGETで送られてきた文字列を変数に保存しますので、そのときに文字列に仕込んだコマンドが実行されることになって非常に危険です。次の例は、騒ぎの中、私のウェブサーバに飛んできたリクエストのログです。パスワードファイルを盗み見しようとしています。

xxx.yyy.zzz.aaa - - [25/Sep/2014:08:32:26 +0900] "GET / HTTP/1.1" 302 208
 "-" "() { :;}; echo Content-type:text/plain;echo;/bin/cat /etc/passwd"

ところで、「CGIでbashが立ち上がるなんて、こんな本を書いたお前のところだけだろ」という声も聞こえて来そうなんですが、CGIスクリプトからコマンドを読んでおり、shと打つとbashが代わりに立ち上がる環境でウェブサーバが動作しているという場合、知らないうちにbashが立ち上がっていますので、ご注意ください。当然、最新のbashではこのバグは潰されています。

第4位 (2016年9月・悪用危険

H4sICBmZ4lcAA2VsZgCrd/VxY2RkZIABJgZmBhAvMcBEyIQBAUwYFBhgquCqgWpAVDMUs4I4AgwMjxvbHjdNftw4mQuodgcLUHA3SMvOEKD6XbxA1tmGHSCB3QxgNgCMjcoWgwAAAA==

これはワンライナーでなく、ワンライナーで解く対象となる暗号です。なぜかTwitter上でシェル芸暗号解読大会が開催された時に私が考えた「Twitterに実行ファイルをエンコーディングして乗っけようとして頑張ってたら乗ってしまったやつ」です。こちらのサイトからELF(実行バイナリ)を作り、それをzipやbase64で変換したものです。

次のように実行できます。

takeda@jooy:~$ base64 -d hoge | gunzip > a ; chmod +x a ; ./a
うんこ

ところでこの問題、昨日発売された、Software Design 2017年1月号に似た問題が出ています(ネタバレになったら申し訳なく)。Software Design 2017年1月号で、特集で「シェル30本ノック」というのをシェル芸勉強会周辺の方々と書きました。「ワンライナー4) いつもお世話になっている編集のYさんは、頑なに「シェル芸という言葉は使わないのです。ブームの火付け役なのに。たぶん、ブレーキかけないと暴走し出すと思ってるのではなかろうか。正解。中心に40ページ」ということで、1人じゃ無理なので、シェル芸勉強会の周りの変態さん腕利きの方々に参加を募り、Slackでチームを作ってGitHubでわーっと書いていきました。SoftwareDesignのきっちりしているところと、シェル芸勉強会の奔放なところをうまく両立できていると思いますので、ぜひご一読を。

以上、宣伝でした。

第3位(2014年8月・安全)

$ eval eval \''n='\''{1..'$(dc -e 1000vp)'}'\'' eval eval eval echo '\'\\\\\\\\\\\\\\\'\\\\\\\'\\\'\''$(('\'\\\'\\\\\\\'\\\'\''$n'\'\\\'\\\\\\\'\\\'\''*'\'\\\'\\\\\\\'\\\\\\\\\\\\\\\'\\\'\''{2..$((1000/n))}'\'\\\'\\\\\\\\\\\\\\\'\\\\\\\'\\\'\''))'\'\\\'\\\\\\\'\\\\\\\\\\\\\\\'\'';'\' | tr ' ' \\n | sort -n | uniq -u

第3位、こちらも古いんですが、あまりにも変態すぎるので未だシェル芸界隈では語り草になっている鳥海師匠の「変態素数ワンライナー」です。上のワンライナーをコピペして動かしてみてください。ちゃんと動きます。そして、安心・安全です。

cafy@upin:~$ (変態すぎてSyntaxhilighterがうまく動かないので省略) | head
2
3
5
7
11
13
17
19
23
29

ちゃんと動く以外、詳細不明です。

第2位 (2016年4月30日・そこそこ危険

$ alias eval='eval eval'
$ eval

さて第2位です。これも鳥海師匠の講義の最中に飛び出した「イーバル!イーバルイーバル!!イーバル!!!」です。「ちょっと!ちょっとちょっと!」のニュアンスで1行目を読み込み、「バルズ!!」のニュアンスで2行目を実行すると、端末が死にます。コンソールでやるとPCがシャットダウンします。ちょっと、気持ちいいです。

死ぬ原理ですが、forkbombのマイルドバージョンで、2行目のevalを実行するとeval evalに置き換わってeval evalが実行され、さらにevalが二つに分裂し・・・ということでevalがたくさんになってbashがパンクして死にます。

端末で行う場合、被害としてはその端末が落ちるだけですので、皆さんもスタバ等でドヤリングする際は、exitの代わりに

cuta@findtravel:~$ alias eval='eval eval'
cuta@findtravel:~$ eval

と打って(キーボードは強打すること)、かっこよく端末を閉じるグッドプラクティスを身につけてはいかがでしょうか。何が起きても私は責任を取りませんが。

第1位 (2016年4月・安全)

$ l='L${r}FR${l}F${l}RF${r}L' r='R${l}FL${r}F${r}LF${l}R' eval eval eval eval eval eval l= r= eval echo '$l' | { read a; b=${a%%F*}; echo "from turtle import *;speed(0);pensize(2);ms=min(screensize())*0.8;l=2*ms/(2**${#b}-1);up();setpos(-ms,-ms);down();${a}done()"; } | sed 's/L/lt(90);/g;s/R/rt(90);/g;s/F/fd(l);/g' | python

さて今回の第1位は、鳥海師匠の「ヒルベルト曲線ワンライナー」です。デスクトップ環境でお楽しみください。以下は本人による実行例です。

解説はこちらの@hexominoさんのLT資料にあります。変数に再帰的に経路を埋め込んで行って、最後にPythonに食わせて実行するという手順のようです。ワンライナーもご本人の了承を得て@hexominoさんの資料から拝借しました。

うん。わからん。

最後に

ということで、鳥海師匠の1〜3位独占で終わりました。某サイト群と違って師匠には快諾を得て書いておりますが、こうやって人のやったことでブログを書いていると、やっぱり自分の手柄は本人が自分の言葉で書いた方がいいんじゃないかなあと思ってしまいます。

師匠におかれましては、ぜひ「今日から俺はシェル芸で飯を食うんだ」とご決心いただければ幸いです。

以上。

Pocket
LINEで送る

脚注   [ + ]

1.  ふんどしを脱ぐと立派な鰹節が出現するイメージの下ネタです。
2.  かなりイキってるインタビューである https://m.newspicks.com/news/651502/body/?sentlog を参考にさせていただきました。
3.  マイナンバーに抜けがないか、みんなで仲良く襲撃検証した事件。
4.  いつもお世話になっている編集のYさんは、頑なに「シェル芸という言葉は使わないのです。ブームの火付け役なのに。たぶん、ブレーキかけないと暴走し出すと思ってるのではなかろうか。正解。

【問題と解答】第25回もう4年もやってんのかシェル芸勉強会

Pocket
LINEで送る

イントロ

こちら

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.25

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

今回はUbuntu Linux 16.04で解答例を作りました。

Q1

www.usptomo.comのIPアドレスだけを出力するワンライナーを考えてみてください。

解答

$ dig www.usptomo.com | grep -A1 ANSWER 
| tail -n 1 | awk '{print $NF}'
157.7.203.188
$ ping -c1 www.usptomo.com | head -n 1 
| awk '{print $3}' | tr -d '()'
157.7.203.188

Q2

次のような出力を作ってください。(出典

ひらけ!ポンキッキ
らけ!ポンキッキひ
け!ポンキッキひら
!ポンキッキひらけ
ポンキッキひらけ!
ンキッキひらけ!ポ
キッキひらけ!ポン
ッキひらけ!ポンキ
キひらけ!ポンキッ

解答

ベタなものを載せておきます。変態的解答はウェブで。

$ a="ひらけ!ポンキッキ" ; for i in $(seq 2 $(wc -m <<< $a)) ; 
do echo $a ; a=$(sed 's/\(.\)\(.*\)/\2\1/g' <<< $a) ; done

Q3

rbashと打つとリダイレクトが使えなくなります。

この状況で、/etc/passwdからbashをログインシェルにしているユーザのレコードを抽出し、hoge等のファイルに出力してみましょう。様々な方法を考えてみましょう。bashと打ったりexitでもとのbashに戻るのは反則とします。

解答

$ grep bash$ /etc/passwd | tee hoge
$ grep bash$ /etc/passwd | awk '{print $0 > "huge"}'
$ grep bash$ /etc/passwd | dd of=hohe

Q4

以下のひらがなからワンライナーを始めて、濁点がつく字だけに濁点をつけてみてください。

$ echo すけふぇにんけん

解答

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

Q5

1秒に一つ*が伸びていくアニメーションを作ってください。

解答

$ yes | awk 'BEGIN{a="*"}{print a;a=a"*";system("sleep 1")}' 
| xargs -I@ echo -ne @"\r" 

Q6

日本語のメッセージから作った次の文字列を復元してください。

$ cat crypt 
b730a730eb30b8820a00

解答

0a00あたりがカギになります。

$ cat crypt | xxd -ps -r | iconv -f=ucs-2le -t=utf8
シェル芸
$ echo -ne $(sed 's/\(..\)\(..\)/\\U\2\1/g' < crypt)
シェル芸

Q7

本日(2016年10月29日)の範囲の毎秒のUNIX時刻で素数となるものを全て列挙してください。出力はUNIX時刻でなく、何時何分何秒か分かるようにしましょう。世界標準時で考えてください。

解答

$ ( date -ud '20161029' +%s ; date -ud '20161030' +%s ) | xargs seq 
| factor | awk 'NF==2{print "@"$2}' | date -uf - 

Q8

次のようにサイン波を描いてください。

%e3%82%b9%e3%82%af%e3%83%aa%e3%83%bc%e3%83%b3%e3%82%b7%e3%83%a7%e3%83%83%e3%83%88-2016-10-27-21-04-17

解答

$ seq 1 20 | awk '{a=sin($1/3) * 10 + 10;for(i=0;i<a;i++)printf "@ ";
printf "* ";for(i=a;i<20;i++)printf "@ ";print ""}' 
| rs -t 23 | tr @ ' ' 
Pocket
LINEで送る

【問題と解答】第24回◯◯o◯裏番組シェル芸勉強会

Pocket
LINEで送る

問題のみのページはこちら

イントロ

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.24

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

今回はUbuntu Linux 16.04で解答例を作りました。

Q1

$ cat Q1
玉子 卵 玉子 玉子 玉子 玉子
玉子 玉子 卵 卵 卵 玉子
卵 玉子 卵 玉子 玉子 玉子
卵 玉子 卵 卵 卵 卵
玉子 卵 玉子

上のようなQ1ファイルについて、次のような出力を得てください。

玉子:5 卵:1 
玉子:3 卵:3 
玉子:4 卵:2 
玉子:1 卵:5 
玉子:2 卵:1 

解答

AWKの力技になります。力技でない方法を募集。

$ cat Q1 |
 awk '{for(i=1;i<=NF;i++){a[$i]++};for(k in a){printf("%s:%d ",k,a[k]);a[k]=0}print ""}'
玉子:5 卵:1 
玉子:3 卵:3 
玉子:4 卵:2 
玉子:1 卵:5 
玉子:2 卵:1 

Q2

次のようなテキストについて、繰り返し出てきた文字の2つ目以降を省いて出力してください。例えばQ2のファイル

$ cat Q2
へのへのもへじ

の場合、「へのもじ」が正解の出力になります。

解答

$ cat Q2 | grep -o . | nl | sort -k2,2 -k1,1n |
 uniq -f 1 | sort | awk '{printf $2}' | xargs
へのもじ
$ cat Q2 | grep -o . | awk '{if(!a[$1]){printf $1};a[$1]=1}END{print ""}'
へのもじ
$ < Q2 grep -o . | awk '{if(!a[$1]){printf $1};a[$1]=1}' | xargs
へのもじ

Q3

$ cat Q3
金 日成
キム ワイプ
金 正日
キム タオル
金 正男

というデータを、

%%
キム タオル
キム ワイプ
%%
金 正男
金 正日
金 日成
%%

というように第一フィールドをキーにして%%でレコードを区切ってください。awkを使ってできた人は、awkを使わないでやってみてください。

解答

$ sort Q3 | awk '{if($1!=a){print "%%";print;a=$1}else{print}}END{print "%%"}'
%%
キム タオル
キム ワイプ
%%
金 正男
金 正日
金 日成
%%
$ sort Q2 | rev | uniq --group=both -f 1 | rev | sed 's/^$/%%/'
%%
キム タオル
キム ワイプ
%%
金 正男
金 正日
金 日成
%%

Q4

Q4.xlsxのA1のセルには数字が書いてあります。その数字を出力してください。A4には文字列が書いてあるので余裕がある人はそれも特定してみましょう。

解答

A1のセル(数字の読み方)

$ unzip -p Q4.xlsx xl/worksheets/sheet1.xml | sed 's;</c>;&\n;g' |
 grep -o '<c.*</c>' | grep A1 | sed 's;.*<v>;;' | sed 's;<.*;;'
114514
$ unzip -p Q4.xlsx xl/worksheets/sheet1.xml | hxselect -s '\n' c |
 grep A1 | hxselect -c v
114514

A2の文字列の読み方。シートには文字列のIDが書いてあるのでこれで文字列のシートを読んで特定。

###これで6番目(0番から始まるので7番目)の文字列とわかる###
$ unzip -p Q4.xlsx xl/worksheets/sheet1.xml |
 hxselect -s '\n' c | grep A4
<c r="A4" t="s"><v>6</v></c>
###抽出###
$ unzip -p Q4.xlsx xl/sharedStrings.xml |
 hxselect -s '\n' si | awk 'NR==7'
<si><t>エクシェル芸</t><rPh sb="5" eb="6"><t>ゲ</t></rPh><phoneticPr fontId="1"/></si>

Q5

ファイルQ5について、xに好きな数を代入して各行の式を計算してください。

$ cat Q5
x + x^2
x + 1/x
x*x*x

余裕のある人は、例えばxに2を代入したければ、

$ echo 2 | ...

というようにecho <代入したい数>から始めてワンライナーで解いてみてください。

解答

例えばこれで解けます。(-2)のカッコはQ5ファイルでは不要なようです。

$ sed 's/x/(-2)/g' Q5 | bc -l
2
-2.50000000000000000000
-8

echo <数字>からスタートすると、ややこしくなります。

$ echo -2 | xargs -I@ awk -v a=@ '{gsub(/x/,a,$0);print}' Q5 | bc -l
2
-2.50000000000000000000
-8

Q6

「玉子」と「卵」の数を数えて、数が少ない方を数が大きい方で置換してください。

$ cat Q6 
卵卵玉子玉子玉子玉子玉子卵卵卵玉子玉子卵玉子玉子玉子玉子卵卵玉子卵玉子卵卵玉子卵玉子

解答

力技です。

$ cat Q6 | grep -oE '(玉子|卵)' | sort | uniq -c |
 sort -n -k1,1n | awk '{print $2}' | xargs |
 awk '{print "s/"$1"/"$2"/g"}' | xargs -I@ sed @ Q6
玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子玉子

Q7

次のseq(あるいはjot等)の出力から、各桁の数字の構成が同じもの(例: 11122と22111等)を重複とみなし、除去してください。

$ seq -w 00000 99999

解答

###asortを使う場合###
$ seq -w 00000 99999 | sed 's/./& /g' |
 awk '{for(i=1;i<=NF;i++)a[i]=$i;asort(a);for(k in a){printf a[k]}print ""}' |
 sort -u
###ちょっと気の利いた方法(数字が小さい順に並んでいるものだけ残す)###
$ seq -w 00000 99999 | sed 's/./& /g' |
 awk '$1<=$2&&$2<=$3&&$3<=$4&&$4<=$5' | tr -d ' ' 

Q8

1. まず、1〜7を全て含む7桁の整数を全て列挙して、tmpというファイルに出力してください。

2. 次に、相異なる7以下の正の整数a,b,c,d,e,f,gを用いて、

abcd + efg

と表せる素数と、その時のa〜gの数字を全て求めましょう。tmpを用いて構いません。

(参考: 2011年日本数学オリンピック予選第3問から。一部改。http://www.imojp.org/challenge/old/jmo21yq.html

解答

1は力技になります。

$ seq -w 0000000 9999999 | grep -v [089] |
 grep 1 | grep 2 | grep 3 | grep 4 | grep 5 | grep 6 | grep 7 > tmp

2は、うまくwhileとfactorを使って求めます。

$ cat tmp | sed 's/./& /g' | awk '{print $1$2$3$4$5$6$7,$1*$2*$3*$4+$5*$6*$7}' | while read a b ; do echo $b | factor | awk -v n=$a 'NF==2{gsub(/./,"& ",n);print n,$2}' ; done 
2 3 4 6 1 5 7  179
2 3 4 6 1 7 5  179
2 3 4 6 5 1 7  179
2 3 4 6 5 7 1  179
2 3 4 6 7 1 5  179
2 3 4 6 7 5 1  179
2 3 6 4 1 5 7  179
2 3 6 4 1 7 5  179
2 3 6 4 5 1 7  179
...
Pocket
LINEで送る

【問題と解答】第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会

Pocket
LINEで送る

問題だけのページはこちら

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.21

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

今回はUbuntu Linuxで解答例を作りましたので、BSD系、Macな方は以下の表をご参考に・・・。

Mac,BSD系 Linux
gdate date
gsed sed
tail -r tac
gtr tr
gfold fold

イントロ

補記

最近あまり本の宣伝をしていないのでシェルプログラミング実用テクニックから問題を持ってきました。

Q1

ShellGeiData/vol.21/Q1のbba.pdfからテキストを抽出して標準出力に出してください。

解答例

例題のファイルの日本語にはFlateDecodeという圧縮がかかっていますが、これを解凍する一般的なコマンドは見つかりませんでした。ですのでpdf用のコマンドを紹介するだけで・・・。FlateDecodeの解凍コマンドはzlibを使うと自作はできる模様。

###poppler-utilsをインストール###
$ sudo apt-get install poppler-utils
###あとはlessとかpdftotextとか###
$ less bba.pdf | cat
  群馬のシャブばばあ




hoge.txt[2016/02/09 22:30:32]
$ pdftotext -q bba.pdf -
群馬のシャブばばあ

hoge.txt[2016/02/09 22:30:32]

Q2

次のデータはShift JIS(cp932)の固定長データです。

$ cat anydata.cp932 
00000001??ӹ޷?ݺ?*******214413051100000002ʰ????ݸ*********114413018800000003???ӷ?ݺ?********210413093100000004??ݷ?ݺ?*********234413000800000005???ް??׳??޷?ݺ?331413090000000006??Э????ݾ޲??ݺ?1234130981

次のようなUTF-8のテキストに変換してください。

00000001ハナモゲギンコウ*******2144130511
00000002ハードバンク*********1144130188
00000003コドモギンコウ********2104130931
00000004ハタンギンコウ*********2344130008
00000005アンダーグラウンドギンコウ3314130900
00000006バミューダメンゼイギンコウ1234130981


解答

###Shift JISの半角は1バイトなのでUTF-8に変換する前に折り返すと楽です。###
$ cat anydata.cp932 | fold -b35 | nkf -wLux
00000001ハナモゲギンコウ*******2144130511
00000002ハードバンク*********1144130188
00000003コドモギンコウ********2104130931
00000004ハタンギンコウ*********2344130008
00000005アンダーグラウンドギンコウ3314130900
00000006バミューダメンゼイギンコウ1234130981

###1行の長さを調べるときは仕様書を見るか、規則性を見つけて折り返して長さを調べる###
$ cat anydata.cp932 | sed 's/[0-9]\{10\}/&\n/g' |
 LANG=C awk '{print length($0)}'
35
35
35
35
35
35
1
1

Q3

2016年の日曜日を全て列挙してください。

解答

GNU dateの-fを使うと楽です。

$ seq 20160101 20161231 | date -f - 2> /dev/null | grep 日曜日
2016年  1月  3日 日曜日 00:00:00 JST
2016年  1月 10日 日曜日 00:00:00 JST
2016年  1月 17日 日曜日 00:00:00 JST
...
2016年 12月 18日 日曜日 00:00:00 JST
2016年 12月 25日 日曜日 00:00:00 JST
###Tsukubaiを使う例###
$ mdate -e 20160101 20161231 | tr ' ' '\n' | yobi 1 | awk '$2==0'
20160103 0
20160110 0
20160117 0
...
20161218 0
20161225 0

Q4

次のデータファイル

001 あみだばばあ
002 砂かけばばあ
003 ******
004 尾崎んちのババア

に、次の新しいデータ

002 *******
003 群馬のシャブばばあ
005 純愛ババア学園

を反映して

001 あみだばばあ
002 *******
003 群馬のシャブばばあ
004 尾崎んちのババア
005 純愛ババア学園

というデータを出力してください。

解答

$ sort -ms -k1,1 newdata data | uniq -w 3
001 あみだばばあ
002 *******
003 群馬のシャブばばあ
004 尾崎んちのババア
005 純愛ババア学園

Q5

GitHubのvol.21/Q5にある次の二つのシェルスクリプトのデバッグをしてください。

$ cat ./a.bash 
#!/bin/bash

echo Hell
###実行すると変なバグ###
$ ./a.bash 
./a.bash: 行 1: #!/bin/bash: そのようなファイルやディレクトリはありません
Hell
$ cat b.bash 
#!/bin/bash

ls ˜/
###ホームディレクトリが表示されない###
$ ./b.bash 
ls: ˜/ にアクセスできません: そのようなファイルやディレクトリはありません

解答

a.bashについては「BOM付きUTF-8」という凶悪なフォーマットなので発見はバイナリの理解が大きな助けになります。が、とりあえずnkfに通せばBOMは取れます。たまにWindowsからやってきます。

###調べるとUTF-8と出るので発見が遅れる。###
$ nkf -g a.bash 
UTF-8
###xxdで見ると頭に変なバイト列。###
$ xxd -ps a.bash 
efbbbf23212f62696e2f626173680a0a6563686f2048656c6c0a
###ただし、見なくてもnkfで除去できる。###
$ nkf -wLux a.bash > a
$ chmod +x a
$ ./a
Hell

b.bashは、チルダがUTF-8のマルチバイト文字になっていて、~/がホームディレクトリに変換されません。このスクリプトには他にマルチバイト文字がないので、次のようなワンライナーでチルダがおかしいことを発見できます。

$ iconv -c -f utf-8 -t ascii b.bash | diff - b.bash 
3c3
< ls /
---
> ls ˜/

Q6

次の拡張正規表現をワンライナーで基本正規表現に変換してください。括弧の中の数字は数字の回数の文字列の繰り返しに展開してください。

$ cat extended 
a+h{5}(ho){10}[0-9]+

解答

ゴリゴリです。

$ cat extended | sed 's/[+}]/&\n/g' | sed 's/\(.*\)+/\1\1*/' |
 tr '{}()' '    ' |
 awk 'NF==2{for(i=1;i<=$2;i++){printf $1};print ""}NF==1' |
 tr -d '\n' | xargs
aa*hhhhhhohohohohohohohohoho[0-9][0-9]*

Q7

GitHubのvol.21/Q7にあるテキストについて、各段落の文字数を数えてください。

解答

改行をとって数える対象を1行にまとめる方針が簡単です。解答例はロケールが日本語で、awkがgawkである等、いろいろ制約がありますが・・・。

$ cat text | tr -d '\n' | sed 's/ /\n/g' |
 awk '{print length($1),$1}'
0 
15 恥の多い生涯を送って来ました。
353 自分には、人間の生活というものが、...にわかに興が覚めました。
103 また、自分は子供の頃、...とばかり思っていました。

Q8

GitHubのvol.21/Q8にある1350369599.Vfc03I4682c8M940114.remoteから添付ファイルを抽出して画像を復元してください。二つありますが別々に処理して構いません。

解答

まず、何行目から何行目までがデータなのか調べます。

$ grep -n -C 1 -- -- 1350369599.Vfc03I4682c8M940114.remote 
(略)
59:--047d7b621ee6cf83c604cc276bb3
60-Content-Type: image/jpeg; name="CHINJYU.JPG"
--
665-0000000000000000000000000000001//9k=
666:--047d7b621ee6cf83c604cc276bb3
667-Content-Type: image/jpeg; name="IMG_0965.JPG"
--
77341-xk9On61jS6VNFJqFxdoIZYbWK6QALsnJbBjHYcc4GT2IHJrGhUevkZ1MNypPuf/Z
77342:--047d7b621ee6cf83c604cc276bb3--

で、その範囲を抽出して変換します。一つめの画像の切り出しの例だけ示しておきます。

###出力の範囲を見ながらデータを切り出す###
$ sed -n '60,665p' 1350369599.Vfc03I4682c8M940114.remote |
 sed -n '6,$p' | base64 -d > a.jpg
###ImageMagickのidentifyコマンドでちゃんと画像になっているか確認###
ueda@remote:~/GIT/ShellGeiData/vol.21/Q5$ identify a.jpg 
a.jpg JPEG 261x261 261x261+0+0 8-bit DirectClass 34.2KB 0.010u 0:00.019
###さらにavplayで画像を見る###
$ avplay a.jpg

Pocket
LINEで送る

【問題のみ】第21回未経験者大歓迎!誰でも働けるアットホームな職場ですシェル芸勉強会

Pocket
LINEで送る

解答はこちら。

問題で使うファイル等

GitHubにあります。ファイルは

https://github.com/ryuichiueda/ShellGeiData/tree/master/vol.21

にあります。

クローンは以下のようにお願いします。

$ git clone https://github.com/ryuichiueda/ShellGeiData.git

環境

今回はUbuntu Linuxで解答例を作りましたので、BSD系、Macな方は以下の表をご参考に・・・。

Mac,BSD系 Linux
gdate date
gsed sed
tail -r tac
gtr tr
gfold fold

イントロ

補記

最近あまり本の宣伝をしていないのでシェルプログラミング実用テクニックから問題を持ってきました。

Q1

ShellGeiData/vol.21/Q1のbba.pdfからテキストを抽出して標準出力に出してください。

Q2

次のデータはShift JIS(cp932)の固定長データです。

$ cat anydata.cp932 
00000001??ӹ޷?ݺ?*******214413051100000002ʰ????ݸ*********114413018800000003???ӷ?ݺ?********210413093100000004??ݷ?ݺ?*********234413000800000005???ް??׳??޷?ݺ?331413090000000006??Э????ݾ޲??ݺ?1234130981

次のようなUTF-8のテキストに変換してください。

00000001ハナモゲギンコウ*******2144130511
00000002ハードバンク*********1144130188
00000003コドモギンコウ********2104130931
00000004ハタンギンコウ*********2344130008
00000005アンダーグラウンドギンコウ3314130900
00000006バミューダメンゼイギンコウ1234130981


Q3

2016年の日曜日を全て列挙してください。

Q4

次のデータファイル

001 あみだばばあ
002 砂かけばばあ
003 ******
004 尾崎んちのババア

に、次の新しいデータ

002 *******
003 群馬のシャブばばあ
005 純愛ババア学園

を反映して

001 あみだばばあ
002 *******
003 群馬のシャブばばあ
004 尾崎んちのババア
005 純愛ババア学園

というデータを出力してください。

Q5

GitHubのvol.21/Q5にある次の二つのシェルスクリプトのデバッグをしてください。

$ cat ./a.bash 
#!/bin/bash

echo Hell
###実行すると変なバグ###
$ ./a.bash 
./a.bash: 行 1: #!/bin/bash: そのようなファイルやディレクトリはありません
Hell
$ cat b.bash 
#!/bin/bash

ls ˜/
###ホームディレクトリが表示されない###
$ ./b.bash 
ls: ˜/ にアクセスできません: そのようなファイルやディレクトリはありません

Q6

次の拡張正規表現をワンライナーで基本正規表現に変換してください。括弧の中の数字は数字の回数の文字列の繰り返しに展開してください。

$ cat extended 
a+h{5}(ho){10}[0-9]+

Q7

GitHubのvol.21/Q7にあるテキストについて、各段落の文字数を数えてください。

Q8

GitHubのvol.21/Q8にある1350369599.Vfc03I4682c8M940114.remoteから添付ファイルを抽出して画像を復元してください。二つありますが別々に処理して構いません。

Pocket
LINEで送る

【メモ】ImageMagick(convertコマンド)で3枚以上の画像を合成する

Pocket
LINEで送る

単なるメモですが日本語で手っ取り早いエントリーがなかったので。以下のドキュメントを読んでやってみました。

http://www.imagemagick.org/script/command-line-options.php?#evaluate-sequence

バージョンはこれです。Macでやってます。

$ convert --version
Version: ImageMagick 6.9.2-3 Q16 x86_64 2015-10-06 http://www.imagemagick.org
Copyright: Copyright (C) 1999-2015 ImageMagick Studio LLC
License: http://www.imagemagick.org/script/license.php
Features: Cipher DPC Modules 
Delegates (built-in): bzlib freetype jng jpeg ltdl lzma png tiff xml zlib

この5枚を合成します。これもImageMagickで連結しました。($ convert +append *.png ../a.png)

b

実行。maxのほかにmeanとかminとかあります。

uedamb:tmp ueda$ convert *.png -evaluate-sequence max ../a.png

できたのがこれ。

a

時間を食ってしまったけどこれで論文が完成する・・・。

Pocket
LINEで送る