GlueLangのwhere句の実装

Pocket
LINEで送る

 GlueLangは、その場で使うファイルを次のような書き方で作れます。Haskellから拝借しました。bashの$()がコマンドの引数にあると綺麗に見えないので、whereの中にそういう細かい処理は押し込んでしまおうという意図です。

import PATH

#passwdファイルの一番下のユーザの名前でpasswdファイルをgrepする
grep re '/etc/passwd'
  where
    str re = tail -n 1 '/etc/passwd' >>= awk '-F:' '{print $1}'

bashだとこうなります。

grep $( tail -n 1 '/etc/passwd' | awk '-F:' '{print $1}' ) '/etc/passwd'

 これの実装をするにはスコープを真面目に設計・実装する必要がありますが、GlueLangはシェルなので、基本「スコープはforkしたときに持っていた情報の範囲」で良く、whereのためだけにスコープを作ることになります。これがこれまでグダグダだったので、昨夜遅くコソコソと直してました。具体的には、

  • 変数に、どのジョブに属するのかIDをつける
  • 各要素が解釈されたときに、要素のインスタンスにこれまで分岐してきたジョブのリストを渡す
  • 変数を探すときに、そのリストの逆向きたどる

という処理を加えました。リストを解釈された要素全部に渡すので無駄なのと、ジョブが消えても変数が残ったままになっているという状況ですが、あとから改善します。

Pocket
LINEで送る

GlueLangに標準入力を読みながら実行するループを実装

Pocket
LINEで送る

昨日の続きです。今日は大学で卒業に関するイベント等々があって酔っ払って帰ってきましたが、勢いで開発を進めました。

今日は、bashの次のような処理をGlueLangに実装しました。

###こんなスクリプト###
$ cat hoge.bash 
#!/bin/bash

seq 1 3 |
while read a ; do
	echo "@" $a
done
###こんな出力###
$ ./hoge.bash
@ 1
@ 2
@ 3

GlueLangだと次のようになります。標準入力から1行ごとに配列argvに文字列が読み込まれ、foreachの下に書いた処理が繰り返されます。

###こんなスクリプト###
$ cat hoge.glue 
import PATH

seq 1 3 >>= foreach
  echo '@' argv[1]
###こんな出力###
$ glue ./hoge.glue 
@ 1
@ 2
@ 3

こんな感じです。寝る。

Pocket
LINEで送る

GlueLangにループを実装

Pocket
LINEで送る

 帰省中に少し時間があったので、GlueLangにループを実装しました。次のように使います。この例は、dateにUnix時刻を吐かせて、5で割り切れる数になったらループを抜ける処理です。testコマンドが0でない終了ステータスを返したのを受けてループが終わって最終行のechoが実行されます。

$ cat hoge.glue 
import PATH

loop
  str t = date '+%s' >>= awk '{print $1%5}'
  echo t
  test t -ne 0
  sleep 1

echo 'end'

 実行すると、ちゃんと動きます。これはMacで動かしましたが同じコードでLinuxでも動きます。

$ glue ./hoge.glue 
1
2
3
4
0
end

shのwhileのように書くには

 shやbashのように、 while <コマンド> ; do <処理> ; done と書く場合、つまりコマンドの終了ステータスで処理を実行するかしないかを決めるときは、1段ネストが深くなりますが、次のように記述できます。

$ cat hoge2.glue 
import PATH

loop
  str t = date '+%s' >>= awk '{print $1%5}' #この行と
  test t -ne 0 >> do                        #この行のdoの前までが条件
    echo t                                  #doのあとが繰り返したい処理
    sleep 1

echo 'end'

 ネストが2段になりますが、shやbashのwhileよりも長く条件となるコマンドが書けます。だいたい、while hogehoge ; do …という書き方が、hogehogeという部分をコマンドだと気づかない初心者を量産しており悪い影響を与えているので、踏襲するわけにはいけません。

文法エラーの時に止める

で、シェルでループを作るとCtrl+Cやスクリプトにエラーが思うように止まらない場合がありますが、GlueLangでは止められるように工夫をしました。次の例は、コマンドが見つからない時にすぐにループを止めて、最終行の echo ‘end’ が実行されないことを確かめる例です。

$ cat hoge3.glue 
import PATH

loop
  str t = date '+%s' >>= awk '{print $1%5}'
  eho t     #ここでエラーが起こって処理全体が止まる
  sleep 1
  test t -ne 0

echo 'end'  #これは実行されない

 GlueLangでは(まだ実装が中途半端ですが)「コマンドが実行されて返ってくる終了ステータス」と「コマンドが見つからない、あるいはGlueLangのスクリプト自体が出すエラー」を区別することにしました。技術的には可能ですし、これは普通のシェルよりもエラーへの対応がかなりスマートになるのではないかと考えています。

$ glue ./hoge3.glue 

Parse error at line 2, char 1
	line2: eho t
	       ^

	Command eho not exist
	
	process_level 1
	exit_status 2
	pid 30839

	glue exit_status: 2

Execution error at line 3, char 1
	line3: loop
	       ^
	line4:   str t = date '+%s' >>= awk '{print $1%5}'
	line5:   eho t
	line6:   sleep 1
	line7:   test t -ne 0
	line8: 

	Command error
	
	process_level 0
	exit_status 2
	pid 30837
###echo 'end'が実行されずに終わる###

 ただ、現状で先ほどのように2段にネストした場合、止まらないのでまた来週末あたり改良します。また、readも実装しないといけません・・・。

Pocket
LINEで送る

Raspberry Piで学ぶ—の最初の訂正

Pocket
LINEで送る

出版前に訂正第一号が出てしまいました。

本の中で、「プログラマ向けで絶版になってないソフトウェアライセンスの本が見当たらない」ということを迂闊にも書いてしまったのですが、調査不足でした。電子書籍でありました。早速読みましたが、プログラマ向けにちょうど良い内容でした。

この本、GitHubで正誤表を管理しようとしてたので、早速反映しました。

本の中身はもう修正できず「いい本がない」と言ってしまったので、こちらでなるべくフォローさせていただきます・・・。

Pocket
LINEで送る

「Raspberry Piで学ぶ ROSロボット入門」という本を書きました

Pocket
LINEで送る

ロボットにラズパイを載っけてROSで動かすという流行りもの全部乗せの節操のない本を書きました。3月30日に出ます。以前の日経Linuxの連載をまとめて、原型を留めないほどROS化したものです。本日校了ということで、9月から12月までは執筆、1月からは書き直しや校正と、充実した地獄が終わりました。

 

 

まさか自分がROSの本を書くとは思っていませんでした。私のROSに関するコントリビューションは、たまにROS Wikiを翻訳するくらいです。あんまりROSのコミュニティーに仁義が切れてないのは、別のコミュニティーをやってる身としては褒められたものではないという認識なのですが、日経Linuxの内容を強化する上でROSが避けられず、自分も真正面から扱うことにした次第です。

本の中ではこんなことをしています。

内容は大学の講義や実習を想定しています。4月からの講義にはギリギリですが、ぜひ本を手にとっていただければと。

Pocket
LINEで送る

GlueLangの仕切り直しメモ

Pocket
LINEで送る

突然情報の学科からロボットの学科に戻ることになって止まっていたGlueLangの開発をちょぼちょぼと再会することにしました。

ただ、ドキュメントがないと開発の指針も立たないし、何やってるか外から分からないので、ドキュメントを作っていくことにしました。

ドキュメントはこちらです。このドキュメントのソースはこっちです。

GlueLangのリポジトリはこちらです。

Pocket
LINEで送る

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

今更ですが・・・

次回は2月11日 or 18日で調整中です。

当日の様子

午前

午後

イントロ

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

問題

こちら

まとめ

サテライト会場の様子

福岡

大阪

LT(とりあえず東京のアップされてる分)

スライドアップしたら教えてくださーい!

Pocket
LINEで送る