第29回シェル芸勉強会まとめ

Pocket
LINEで送る

今回も共催の日本UNIXユーザ会様、会場提供のさくらインターネット様、参加者の皆様のご協力のもと、シェル芸勉強会を開催しました。

今回の問題は、ここ数回では難易度が下がったようで、会場では安堵の声、体力を奪われなかったという声が聞かれました(どんな会なんだ・・・)。

以下、単にリンクの貼り付け集ですが、当日の様子が分かるまとめです。

Twitterまとめ

録画

あと、大阪のLTの録画がありますが、それは大阪のレポートから辿っていただければと。

サテライト会場の様子

大阪、福岡で開いていただきました。ありがとうございました。

福岡

大阪

LTなどのスライドやブログ

大阪のLTは(やばすぎるので、ということではないですが)大阪からのレポートにお任せします。

ブログなどなど、書いたら教えてくださーい。

Pocket
LINEで送る

【問題と解答】第29回激しいシェル芸勉強会

Pocket
LINEで送る

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

問題で使うファイル等

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

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

にあります。

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

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

環境

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

イントロ

Q1

次の2つのファイルは、講義で出した課題1,2それぞれの点数です。

$ cat kadai1
001 山田 20
002 出川 30
005 鳥海 44
$ cat kadai2 
001 山田 20
003 上田 15
004 今泉 22
005 鳥海 44

両方に名前のある人については点数を合計して、次のように全員の得点リストを作ってください。

001 山田 40
002 出川 30
003 上田 15
004 今泉 22
005 鳥海 88

解答

$ join -a 1 -a 2 -1 1 -2 1 kadai{1,2} | awk '{print $1,$2,$3+$5}'
001 山田 40
002 出川 30
003 上田 15
004 今泉 22
005 鳥海 88

Q2

次の2つのファイルは、5回の講義の出欠と6回目の講義で出席した人の番号のデータです。attendに6回目の講義の出欠を反映したデータを標準出力に出力してください。

$ cat attend
001 山田 出出欠出出
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
$ cat attend6
001,005,003

解答

$ tr , '\n' < attend6 | sort | sed 's/$/ 出/' |
 join -a 1 attend - |
 awk 'NF==3{print $0"欠"}NF==4{print $1,$2,$3$4}'

Q3

次の2つのファイルは5回の講義の出欠とテストの成績を記録したファイルです。

###$1: 番号, $2: 名前, $3: 出欠 ###
$ cat attend 
001 山田 出出欠出出 
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
###$1: 番号, $2: テストの点数(受けてない人のデータは無い)###
$ cat test 
001 90
002 78
004 80
005 93

こういうルールで、最終的な点数を出して、番号、名前、点数を記録したファイル作ってください。

  • 出席が過半数に満たない人、テストを受けていない人は0点
  • 出席が過半数の人はテストの点数を採用

解答

$ join -a 1 -o 1.1 1.2 1.3 2.2 -e 0 attend test |
 awk '/(.*欠){3}/{$4=0}{print}'
001 山田 出出欠出出 90
002 出川 出出欠欠欠 0
003 上田 出出出出出 0
004 今泉 出出出出出 80
005 鳥海 欠出欠出欠 0

Q4

Q4.1

次の出力をパイプで受けて

$ echo -1 4 5 2 42 421 44 311 -9 -11

次のように同じ桁のものを横並びに出力を得てください。横に並べる時の順番は任意とします。また、この出力のように正の数と負の数を分けます。

-11 
-9 -1 
2 4 5 
42 44 
311 421 

Q4.2

次の出力をパイプで受けて

$ echo -1 +4 5 2 42 421 44 311 -9 -11

次のように同じ桁のものを横並びに出力を得てください。Q1.1と同じく横に並べる時の順番は任意とします。

-11 
-9 -1 
2 +4 5 
42 44 
311 421 

解答

Q4.1

$ echo -1 4 5 2 42 421 44 311 -9 -11 | xargs -n 1 | sort -n |
 awk 'length(a) != length($1){print ""}{printf("%d ",$1);a=$1}' |
 awk 'NF'
-11 
-9 -1 
2 4 5 
42 44 
311 421 

Q4.2

awk内で1をかけると+符号が外れるので、符号を外して桁数を比較すると先ほどの解答例が転用できます。

$ echo -1 +4 5 2 42 421 44 311 -9 -11 | xargs -n 1 | sort -n |
 awk 'length(a*1) != length($1*1){print ""}{printf("%s ",$1);a=$1}' |
 awk 'NF'
-11 
-9 -1 
+4 2 5 
42 44 
311 421 

Q5

次のファイルの中身について、

$ cat triangle 
   1
  3 9
 7 a 6
8 4 2 5

次のように右に転がしてください。できる人はawkを使わないでやってみましょう。

   8   
  4 7  
 2 a 3 
5 6 9 1

解答

四角にして回すと楽です。

$ cat triangle | sed 's/ /0 /g' | sed 's/\([^ ]\)0/\1/g' |
 tac | rs -T | tr -d 0 | sed 's/  / /g' | sed '1s/^/   /' |
 sed '2s/^/  /'  | sed '3s/^/ /'
   8   
  4 7  
 2 a 3 
5 6 9 1

Q6

次の1から100までの素数を書いたファイル(いくつか欠番が存在)について、

$ cat prime 
2 3 5 7 11 13 17 19 31 37 41 43 47 53 59 67 71 73 79 83 89 97

次のように欠番のところで折り返してください。(ワンライナーの中に欠番を直接書かないでくださいね。)

2 3 5 7 11 13 17 19 
31 37 41 43 47 53 59 
67 71 73 79 83 89 97

解答

$ cat prime | xargs -n 1 | cat - <(seq 1 100 | factor |
 awk 'NF==2{print $2}') | sort -n | xargs |
 awk '{for(i=1;i<NF;i+=2){if($i==$(i+1)){printf("%d ",$i)}else{print "";i-=1}}}' |
 awk 'NF'
2 3 5 7 11 13 17 19 
31 37 41 43 47 53 59 
67 71 73 79 83 89 97 

Q7

リポジトリ内のnyaan.htmlは、ブラウザで見ると次のように見えます。

次のようにcatから始めて、この文字を(大きなまま)端末上に表示してみてください。

$ cat ./nyaan.html | ...

できる人は小さい通常の文字で「にゃーん」と出してみてください(これは解答例を考えていません)。

解答

$ cat ./nyaan.html | nkf --numchar-input |
 sed 's/<[^<]*>//g' | sed 's/&quot;/"/g'

Q8

次のshellgeiファイルについて、

$ cat shellgei 
                                            m                         
   ""m                        m  "m          #    # #           #     
  mm                           #  #          #mmm"""          m"      
    "    m"      mmm""         #  #   #     m"   #        mm""m       
       m"          #mm        m"  # m"     "    #             #       
  "mm""         """"  "      m"   #"          m"              #       
                                                                      
                   

次のように、文字の無い列を詰めてください。

                          m               
 ""m             m "m      #    # #      #
mm                # #      #mmm"""     m" 
  "    m" mmm""   # #   # m"   #   mm""m  
     m"     #mm  m" # m" "    #        #  
"mm""    """"  "m"  #"      m"         #                                     

解答

$ cat shellgei | sed 's/ /@/g' | sed 's/./& /g' |
 awk '{for(i=1;i<=NF;i++){if($i!="@")a[i]=$i}}END{for(i=1;i<=NF;i++){b=a[i]==""?"x":" ";printf b}}END{print ""}' |
 cat - shellgei |
 awk 'NR==1{a=$0}{for(i=1;i<=length($0);i++){if(substr(a,i,1)!="x")printf substr($0,i,1)};print ""}'
                                          
                          m               
 ""m             m "m      #    # #      #
mm                # #      #mmm"""     m" 
  "    m" mmm""   # #   # m"   #   mm""m  
     m"     #mm  m" # m" "    #        #  
"mm""    """"  "m"  #"      m"         #  
                                          
                      

もっと良い解答。

Pocket
LINEで送る

【問題のみ】第29回激しいシェル芸勉強会

Pocket
LINEで送る

解答のページはこちら

問題で使うファイル等

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

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

にあります。

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

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

環境

解答例はUbuntu Linux 16.04 で作成。Macの場合はcoreutilsをインストールしてつかいましょう。BSD系の人は玄人なので各自対応のこと。

イントロ

Q1

次の2つのファイルは、講義で出した課題1,2それぞれの点数です。

$ cat kadai1
001 山田 20
002 出川 30
005 鳥海 44
$ cat kadai2 
001 山田 20
003 上田 15
004 今泉 22
005 鳥海 44

両方に名前のある人については点数を合計して、次のように全員の得点リストを作ってください。

001 山田 40
002 出川 30
003 上田 15
004 今泉 22
005 鳥海 88

Q2

次の2つのファイルは、5回の講義の出欠と6回目の講義で出席した人の番号のデータです。attendに6回目の講義の出欠を反映したデータを標準出力に出力してください。

$ cat attend
001 山田 出出欠出出
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
$ cat attend6
001,005,003

Q3

次の2つのファイルは5回の講義の出欠とテストの成績を記録したファイルです。

###$1: 番号, $2: 名前, $3: 出欠 ###
$ cat attend 
001 山田 出出欠出出 
002 出川 出出欠欠欠
003 上田 出出出出出
004 今泉 出出出出出
005 鳥海 欠出欠出欠
###$1: 番号, $2: テストの点数(受けてない人のデータは無い)###
$ cat test 
001 90
002 78
004 80
005 93

こういうルールで、最終的な点数を出して、番号、名前、点数を記録したファイル作ってください。

  • 出席が過半数に満たない人、テストを受けていない人は0点
  • 出席が過半数の人はテストの点数を採用

Q4

Q4.1

次の出力をパイプで受けて

$ echo -1 4 5 2 42 421 44 311 -9 -11

次のように同じ桁のものを横並びに出力を得てください。横に並べる時の順番は任意とします。また、この出力のように正の数と負の数を分けます。

-11 
-9 -1 
2 4 5 
42 44 
311 421 

Q4.2

次の出力をパイプで受けて

$ echo -1 +4 5 2 42 421 44 311 -9 -11

次のように同じ桁のものを横並びに出力を得てください。Q1.1と同じく横に並べる時の順番は任意とします。

-11 
-9 -1 
2 +4 5 
42 44 
311 421 

Q5

次のファイルの中身について、

$ cat triangle 
   1
  3 9
 7 a 6
8 4 2 5

次のように右に転がしてください。できる人はawkを使わないでやってみましょう。

   8   
  4 7  
 2 a 3 
5 6 9 1

Q6

次の1から100までの素数を書いたファイル(いくつか欠番が存在)について、

$ cat prime 
2 3 5 7 11 13 17 19 31 37 41 43 47 53 59 67 71 73 79 83 89 97

次のように欠番のところで折り返してください。(ワンライナーの中に欠番を直接書かないでくださいね。)

2 3 5 7 11 13 17 19 
31 37 41 43 47 53 59 
67 71 73 79 83 89 97

Q7

リポジトリ内のnyaan.htmlは、ブラウザで見ると次のように見えます。

次のようにcatから始めて、この文字を(大きなまま)端末上に表示してみてください。

$ cat ./nyaan.html | ...

できる人は小さい通常の文字で「にゃーん」と出してみてください(これは解答例を考えていません)。

Q8

次のshellgeiファイルについて、

$ cat shellgei 
                                            m                         
   ""m                        m  "m          #    # #           #     
  mm                           #  #          #mmm"""          m"      
    "    m"      mmm""         #  #   #     m"   #        mm""m       
       m"          #mm        m"  # m"     "    #             #       
  "mm""         """"  "      m"   #"          m"              #       
                                                                      
                   

次のように、文字の無い列を詰めてください。

                          m               
 ""m             m "m      #    # #      #
mm                # #      #mmm"""     m" 
  "    m" mmm""   # #   # m"   #   mm""m  
     m"     #mm  m" # m" "    #        #  
"mm""    """"  "m"  #"      m"         #                                     
Pocket
LINEで送る

Software Design7月号未掲載部分

Pocket
LINEで送る

本日発売です。bashのマニアック機能について「使うなよ!絶対使うなよ!!」というテイストで書きました。

で、宣伝部分だと味気ないので、調子に乗って書きすぎて掲載できなかった部分をあまり加工せずに貼り付けておきまっす。bash3.2とbash4.4で挙動の違う例、4.0以降の新機能の例です。

数字のブレース展開のゼロ埋め

ブレース展開においてゼロ埋めができるようになっています。

bash-3.2$ echo {01..03}
1 2 3
bash-4.4$ echo {01..03}
01 02 03

Unicodeのコードポイント指定

Unicodeのコードポイントを指定して文字を出力できます。

###UnicodeとUTF-8の16進数を指定してみる例###
bash-3.2$ echo -e '\U1F363' '\xF0\x9F\x8D\xA3'
\U1F363 🍣
bash-4.4$ echo -e '\U1F363' '\xF0\x9F\x8D\xA3'
🍣 🍣

次の例は、
この機能とxxdというコマンドを使ってUnicodeから
UTF-8へ変換するワンライナーです。

bash-4.4$ echo -en '\U1F363' | xxd -ps
f09f8da3

case文で使う「;;&」

次のcase文は、SHELLという変数の文字列がbashで終わっている場合に
「bash」と表示するものです。「\*bash」というパターンにマッチして
echoを実行し、次の「\*」は評価されずに終わっています。

bash-3.2$ case $SHELL in *bash ) echo bash ;; * ) echo defalut ;; esac
bash

バージョン4.0ではこの挙動に加え、
「;;&」を用いて次のパターンも評価させることが可能となりました。

bash-4.4$ case $SHELL in *bash ) echo bash ;; * ) echo defalut ;; esac
bash
bash-4.4$ case $SHELL in *bash ) echo bash ;;& * ) echo defalut ;; esac
bash
defalut

大文字を小文字に強制変更する変数

declare -lで変数を宣言すると、代入した大文字が小文字に変換されます。

bash-4.4$ declare -l yesno
bash-4.4$ yesno=YeS
bash-4.4$ echo $yesno
yes                   #小文字になる

また、例は省略しますが、declare -uで宣言すると大文字に変換されます。

普通の変数に対して後から小文字大文字を変換することもできます。
変数の後ろに「^」や「,」をつけます。

bash-4.4$ y=YeS
bash-4.4$ echo ${y^^} #大文字に
YES
bash-4.4$ echo ${y,,} #小文字に
yes
bash-4.4$ echo ${y,}  #1文字目だけ小文字に
yeS

ということで

買って読んでいただければ幸いです。

こちらもお願いしまっす!

Pocket
LINEで送る

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

Pocket
LINEで送る

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

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

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

問題

 

録画

サテライト会場

まとめ

ブログ等

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

番外編

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

Vimシェル芸の予感・・・

Pocket
LINEで送る

【問題のみ】第22回ゴールデンウィークの存在疑惑シェル芸勉強会

Pocket
LINEで送る

解答はこちら

イントロのプレゼン資料

ここです。

問題で使うファイル等

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

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

にあります。

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

$ 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

次のファイルの中身について、「cat <ファイル名>」から初めて、同じワンライナーでそれぞれ中央値を求めてください。データの数が偶数の場合は、中央の二つの値の平均を中央値とします。

ueda@remote:~/GIT/ShellGeiData/vol.22/Q1$ cat a
1
3
4
1
6
6
8
2
ueda@remote:~/GIT/ShellGeiData/vol.22/Q1$ cat b
3.4
13
4242
-4
-5

Q2

次のような出力から初めて、

ueda@remote:~$ echo カレーライス 醤油ラーメン | ...

次のような出力を得てください(表示がずれてますが、「ー」のところで文字列をクロスさせています)。最初のパイプより右側はマルチバイト文字を使わないようにしてみましょう。「ー」が何文字目にあるか等の情報は何でも使って結構です。

      カ
      レ
醤油ラーメン
      ラ
      イ
      ス

Q3

次のデータについて、

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q3
aaabbb
bababa
aaabbb
aaabbb
bababa
bbbbba

次のような出力を得てください。

bababa  2 5
aaabbb  1 3 4
bbbbba  6

次に、得られた答えから元のデータを復元してください。Q3の答えはQ3.ansにあります。

Q4

次のファイルについて、素数行目に存在するりんごとみかんをそれぞれ数えてください。できる人は素数の行を2,3,5,7と明示的に指定しないでやってみてください。

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q4
りんご
りんご
みかん
みかん
りんご
みかん
りんご
りんご

Q5

足して10になる並びを全て見つけてみましょう。

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q5
1 3 4 4 2 3 5 6 7 9 1 4

Q6

次のファイルQ6_1のX,Y,Zに、

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q6_1 
所謂いわゆる「Z」というものにだって、
もっと何か表情なり印象なりがあるものだろうに、
YのからだにXでもくっつけたなら、
こんな感じのものになるであろうか、
とにかく、どこという事なく、見る者をして、
ぞっとさせ、いやな気持にさせるのだ。
私はこれまで、こんな不思議な男の顔を見た事が、
やはり、いちども無かった。

Q6_2に書いてある文字列を当てはめてください。

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q6_2
X 駄馬の首
Y 人間
Z 死相

Q7

明示的に端末を閉じたりシェルを終わらせるためのコマンド(shutdown, reboot, exit, logout等)以外で端末を閉じてみてください。

Q8

次のC++のコードに関数プロトタイプをくっつけてください。

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q8.cc 
#include <iostream>
#include <string>
using namespace std;

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

string nazo(void)
{
	return "謎";
}

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

つまりこういう出力を作ります。

ueda@remote:~/GIT/ShellGeiData/vol.22$ cat Q8.ans.cc 
#include <iostream>
#include <string>
using namespace std;
void aho(void);
string nazo(void);

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

string nazo(void)
{
	return "謎";
}

int main(int argc, char const* argv[])
{
	aho();
	return 0;
}
Pocket
LINEで送る

GitHubのWikiの変更をHubot経由でSlackに通知

Pocket
LINEで送る

シェル芸勉強会の次の日でかなり疲れているのですが、「GitHubのWikiを複数人で編集し、その変更をSlackに飛ばしたい」というニッチな需要ができたので工作活動してました。Slackの標準の機能には、GitHubのWikiの更新を受け取る手段が2016年2月14日現在、無いようです。(あったらすぐ教えてください!30分くらい探してSlack側に受け口が見つからなくてキレてやっちまいました。)issueやpullリクエストの通知機能はあるんですが・・・。

ということで、HubotにGitHubからJSONを飛ばして、Hubotで解釈してSlackに飛ばすことにしました。Hubotについては、次のサイトを参考にインストールを行いました。環境はVPSのUbuntu 14.04上です。

チャットボットでチーム開発効率化入門(1):GitHub製フレームワークHubotの概要とインストール、チャットアプリと連携する基本的な使い方 (1/2) – @IT チャットボットでチーム開発効率化入門(1):GitHub製フレームワークHubotの概要とインストール、チャットアプリと連携する基本的な使い方 (1/2) - @IT
CentOSにHubotを導入してSlackと連携させる – Qiita CentOSにHubotを導入してSlackと連携させる - Qiita

また、CoffeeScriptを書いた時はHubot経由でGitHubのイベントを通知する | SPACEMARKET BLOGを参考にさせていただきました。掲載されているコード(GitHubのissue等をTwitterに飛ばすもの)を、GitHubのwikiをslackに飛ばすように改造しました。

以下はちょっと端折ってますが手順です。

Hubotを召喚する

必要なものを上のサイトを参考にインストール後、適当なディレクトリ(自分の場合は~/HUBOT/GITHUB)を作り、その下で次のコマンドを打ちます。

yo hubot

すると、こんな感じで根掘り葉掘り聞かれます。AAがアホっぽいです。いや、なんでもありません。

$ yo hubot
                     _____________________________  
                    /                             \ 
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             / 
 ======= |[^_/\_]|   /----------------------------  
  |   | _|___@@__|__                                
  +===+/  ///     \_\                               
   | |_\ /// HUBOT/\\                             
   |___/\//      /  \\                            
         \      /   +---+                            
          \____/    |   |                            
           | //|    +===+                            
            \//      |xx|                            

? Owner Ryuichi UEDA <aho@gmail.com>
? Bot name github
? Description A simple notifier for GitHub wiki
? Bot adapter (campfire) slack

間違えてはいけないのは

? Bot adapter (campfire) slack

の一箇所です。

hubotの起動スクリプトを作る

ディレクトリの下のbin/hubotがHubotの起動シェルスクリプトです。これを次のように書き換えます。PORTは、HubotがGitHubからデータを受け取るときに使うポート番号です。

このスクリプトは最後のforeverでサーバに常駐化します。常駐化するとデバッグで止めたり動かしたりするのが面倒なので、
デバッグの時はコメントアウトしている#exec…を使うと良いでしょう。こっちを使うとCtrl+cで止まります。

各種設定

上のスクリプトで次のようになっているところは、自分の環境に合わせて書き換える必要があります。

export HUBOT_SLACK_TOKEN=xxxxxx
export HUBOT_GITHUB_SECRET=yyyyyyy

HUBOT_SLACK_TOKENはSlackのHubotの設定ページに、次のようにトークンが表示されているはずなので、これをコピペして使います。

1455450034

HUBOT_GITHUB_SECRETは、GitHubの連携したいリポジトリのWebhookの設定で、「Add webhook」を押すと、次のように表示されるので、ここの「Secret」に適当なトークンを入れて使います。

1455450001

私は次のような感じで作りました。

$ cat /etc/* | md5sum 2> /dev/null
b720a34fb302c401e5146cefe1ae656d  -

Secretの二つ上にある「Payload URL」は、http://:<ポート番号>/github/webhookにしておきます。このURLの「github」というのはHubotの名前です。

また、リポジトリのどんな変化に対して通知を受け取るかは、「Which events would you like to trigger this webhook?」という項でいじります。「Gollum」というのがWiki関係の通知に相当します。

Hubotスクリプト

こんな風に書きました。Hubotのディレクトリ下のscriptsディレクトリに<なんとかかんとか>.coffeeという名前で置いておくと、bin/hubotを実行すると動き出します。isCorrectSignatureの部分は上に挙げた3番目のブログのコードを整形して使い回しています。

次の部分(19行目)がSlackにデータを投げている部分です。「lab-github」というのは、Slackのチャンネルですので、用途に合わせて変更しましょう。毎度ハードコーティングで申し訳なく・・・

robot.messageRoom 'lab-github', message

スクリプト自体はパースされたJSONのデータを切った貼ったしているだけなので、なんとなく分かる人なら、どんどんいじっていけると思います。GitHubが送ってくるJSONの実物は、さっきのGitHubのリポジトリwebhook設定ページにあります。

Slackには、次のように通知が入ります。(ちょっとデバッグ中のメッセージもありますが。)

スクリーンショット 2016-02-14 21.44.46

表示される情報がURLだけで味気ないので、もうちょっと改良の余地あり。いや、これくらいの方がかえっていいのかも・・・。

寝る。

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で送る

【問題と解答】第20回記念、年末年始の浮ついた気分大粉砕シェル芸勉強会

Pocket
LINEで送る

問題だけページはコチラ

イントロ

問題で使うファイル等

前回からGitHubに置くようにしました。ファイルは

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

にあります。

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

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

環境

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

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

Q1

リポジトリ内のvol.20/Q1ディレクトリには次のように数字が書いてあるファイルが4つ入っています。

$ ls 
file_A-1  file_A-2  file_B-1  file_B-2
$ head -n 2 *
==> file_A-1 <==
1
31351

==> file_A-2 <==
11
35

==> file_B-1 <==
-32
12

==> file_B-2 <==
912
3

file_A-*のグループ、file_B-*のグループからそれぞれ最大の数を探してください。他にfile_C-*、file_D-*、・・・とグループがたくさんあると想定して、1回のワンライナーで両方探すこととします。

解答

$ grep ^ * | sed 's/-[0-9]*:/ /' | sort -k1,1 -k2,2nr |
awk '{print $2,$1}' | uniq -f 1
233333 file_A
9912 file_B

Q2

アンサイクロぺディアのシェル芸のページから、「カースト最上位者が日常的に書く、素数を出力するワンライナー」のコードを取得して実行してください。

解答

$ curl -s http://ja.uncyclopedia.info/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E8%8A%B8 |
grep eval | sed 's/^..//' | bash

Q3

次のファイルについて、奇数を1列目、偶数を2列目に振り分けて、奇数の列を昇順、偶数の列を降順にソートしてください。

$ cat Q3
1
4
2
9
5
8

つまりこうしてください。

1 8
5 4
9 2

解答

$ paste <(awk '$1%2' Q3 | sort) <(awk '$1%2==0' Q3 | sort -r) | tr '\t' ' '
1 8
5 4
9 2
$ cat Q3 | sed 's/.*[02468]$/-&/' | sort | xargs |
awk '{for(i=NF/2;i>=1;i--){print $(NF-i+1),-$i}}'
1 8
5 4
9 2

Q4

今、ログインしているサーバについて、自分の今使っているリモート端末以外の端末を抹殺してください。rootになっても構いません。

解答

もっと楽な方法がありそうですが・・・。ttyコマンドはオプションに$()で埋め込んでもうまく働きません。(ttyが端末と関係ないプロセスで立ち上がるので)。

ueda@remote:~$ a=$(tty | sed 's;/dev/;;') ; ps aux |
awk '$7~/pts\/[0-9]*/' | awk -v "t=$a" '$7!=t' |
awk '{print $2}' | xargs sudo kill 

Q5

任意の二つの自然数をechoして最大公約数を求めましょう。

解答

ueda@remote:~$ echo 45 126 |
awk '{while($1*$2!=0){if($1>$2){$1=$1-$2}else{$2=$2-$1}print}}' |
awk 'END{print $1}'
9
###Tukubai使用(こっちの方が長いが・・・)###
ueda@remote:~$ echo 60 9 | factor | tarr num=1 | tr -d : | 
self 2 1 | sort | count 1 2 | self 1 3 | yarr num=1 |
awk 'NF>2' | awk '{print $1,$2<$3?$2:$3}' |
awk 'BEGIN{a=1}{a*=$1**$2}END{print a}'

Q6

ファイルQ6の中の人の名前について、誰が1列目と2列目の何番めに記述されているかを求めましょう。

###スペースは全角###
$ cat Q6
山田 上田 吉田 武田
吉田 武田 上田 山田

解答例は次のようなものです。

吉田 3 1
山田 1 4
上田 2 3
武田 4 2

解答

$ cat Q6 | sed 's/ / /g' | awk '{for(i=1;i<=NF;i++){print $i,NR,i}}' |
sort -k1,2 | awk '{print $1,$3}' | xargs -n 4 | awk '{print $1,$2,$4}'
吉田 3 1
山田 1 4
上田 2 3
武田 4 2

Q7

一部分に「魚」を持つ漢字をなるべくたくさん列挙してみてください。方法はお任せします。

解答

あくまで一例で一部分ですが・・・

$ seq 39770 40058 | xargs printf "&#x%x;" | nkf --numchar-input 

Q8

次の漢数字をアラビア数字に変換しましょう。

$ cat Q8 
五千七百三十五
四千三
四十五
九万六千二百三十三
十一
百十二

解答

$ cat Q8 | sed 'y/一二三四五六七八九/123456789/' |
nkf -Z1 | sed 's/十/1*10+/' | sed 's/百/1*100+/' |
sed 's/千/1*1000+/' | sed 's/万/1*10000+/' |
sed 's/\([0-9]\)1/\1/g' | bc
5735
4003
45
96233
11
112

宣伝

Pocket
LINEで送る