投稿

2013の投稿を表示しています

ターミナルウィンドウに雪を降らせよう! - Bash Advent Calendar - Day 13

いまは、ぼくのこころの中では 12 月 13 日の 210時ぐらいです。もはや Advent Calendar の体をなしてない気がしますが、細かいことは気にしないで行きましょう。
terminfo 端末エミューレーター(以下「ターミナル」)は色々と標準、デファクトスタンダードが存在します。これから使う ANSI エスケープシーケンスについては、それと同等の機能のあるターミナルであれば、まずもって ANSI エスケープシーケンスに対応しています。
が、ターミナルの機能は ANSI エスケープシーケンスでサポートされているものだけではなく色々あるので、そうした色々な機能を抽象化して定義したのが terminfo です。昔は termcap が主流でしたが、最近は terminfo の方が Linux 界隈では優勢だと思います。 tputコマンド tputコマンドは、terminfoで定義されている機能名を引数にとり、使用しているターミナルに対応するコマンドを出力します。
たとえば、画面クリア "clear" では clear="$(tput clear)"
printf "%q\n" "$clear"
$'\E[H\E[2J' となります。ちなみに、printf %q とか $'...' 記法に「Bashらしさ」があるので、それで記事が書けそうな気がしてきました。 乱数 $RANDOM を参照すると Bash は擬似乱数を返してくれます。が、値は[0, 32767]の範囲とかなりしょぼい仕様です。以下では、頑張って[0, ターミナルカラム数)で一様に分布するっぽい乱数を生成していますが、実用上、Linux であれば rand() {
  local -i r="0x$(
    dd if=/dev/urandom bs=4 count=1 2>/dev/null |
    od -A n -t x4 |
    tr -d ' ')"
  echo $((r % $1))
} でいいでしょう。64bit 環境であれば dd と od の引数に出てくる 4 は 8 に変えてください。
さて、[0, 32767] の範囲でしか値を返さ…

タブ補完(その1) - Bash Advent Calendar - Day 12

いまは、ぼくのこころの中では 12 月 12 日の 234 時ぐらいです。当然「昨日」とは 12 月 11 日のことです(すべて US 太平洋時間)。
compgen関数昨日は補完の仕様をさらっと説明しましたが、実際に補完をどう生成すればいいのかというのを説明していませんでした。COMPREPLYは配列変数なので、この Bash Advent Calendar を初日から読めば、自力でかなりのことができるはずです。

とは言え、Bashさんも鬼ではありません。ありがちなパターンに簡単に対応する関数 compgen 関数が予め用意されてます。、一般的には
COMPREPLY=($(compgen オプション... -- 補完したい単語)) という形で使います。

たとえば "-foo", "-bar", "-buzz" というオプション名を補完させたいとしましょう。そしてユーザーが "-" まで入力している場合には
COMPREPLY=($(compgen -W "-foo -bar -buzz" -- "-")) となります。compgen だけを動作させると以下のようになります
$ compgen -W "-foo -bar -buzz" -- "-"
-foo
-bar
-baz
$ compgen -W "-foo -bar -buzz" -- "-b"
-bar
-baz
$ compgen -W "-foo -bar -buzz" -- "f"
$ echo $?
1 候補が何もなかった場合に、終了ステータスが1になります。

ではよく使うオプションについて説明します。

-W文字列
引数で与えられた文字列を「単語分割」($IFS のいずれかの文字で区切る)して、それを候補とみなします。 補完候補の中に空白が含まれる場合は、IFSを適宜変更しておく必要があります。何を言ってるかわからない人は諦めてくださいw-P文字列
引数で与えられた文字列を、補完候補それぞれの先頭に挿入します。

例えばディレクトリ名を ":" 区切りで入力するとします。…

タブ補完(その0) - Bash Advent Calendar - Day 11

ネタがない。
準備 基本的にありものを使ってね、というのは嫌なのですが、まずは bash-completion というパッケージを導入するのが近道です。そこで共通で使われてる関数達が超絶便利なんです。とりあえず、それをインストールしたら今日はおしまいです。続きは明日。
仕様 ユーザーが入力している情報 とりあえず、自作関数で補完をしようとした場合、以下の変数のお世話になります。

COMP_WORDS
現在入力中の行が、単語分割されて、配列として格納されています。ただし、単語分割は Bash の文法とは関係なく、readline というライブラリが好き勝手に分割してくれます。COMP_WORDBREAKS
上記 readline ライブラリが単語と単語の区切りとみなす文字のリスト。 参照オンリーです。この値を変更することは可能ですが、この値を変更しても readline ライブラリは何もしてくれません。昔は変更すると Bash が死んで楽しかったのですが、最近はそんなことはさすがにないみたいです。COMP_CWORD
現在カーソルがある場所の、その単語が COMP_WORDS で格納されている位置。COMP_LINE
現在入力中の行全体。COMP_POINT
現在のカーソルの場所、COMP_LINEでの文字位置に相当(0スタートなので、行末にカーソルがある場合はCOMP_POINTの長さに同じ) 他にも少し、名前が COMP_ で始まる変数があるのですが、使い道がよくわかりません。
とりあえず ${COMP_WORDS[COMP_CWORD]} で「何となく」のカーソル位置の単語が取れるのですが、COMP_WORDBREAKS に中の文字がカーソル位置の単語に含まれている場合にうまくいきません。 補完候補をユーザーに返す方法 COMPREPLYという配列変数に文字列をセットすると、それらが補完候補とみなされます。これはグローバル変数なので、なんの気にもせず上書きしてオッケーです。 TABでの補完時に自作関数が使われるようにする complete -F 関数名 [-o オプション [-o オプション]... ] コマンド名 で登録が可能です。オプションは以下から複数指定が可能です、というか機能的にどうみても複数指定可能じゃないとおかしいだけど、man ページ読んだだけじゃ分からな…

拡張case文 - Bash Advent Calendar - Day 10

今日も本当に1行もスクリプトも書いてないし、なんの検証もしてない状態でこのブログを書き始めました。途中で破綻しないといいんですけどね。
そもそも、今日のお題はどちらかというと extglob なので、"c" の順番じゃないんじゃないかと思うんですが、所詮は個人でやってる Advent Calendar、細かいことは気にしないでください。

もし気にする方は、代わりにお題をください。いや、気にしない方もこれ読んだらお題をください。
globってなんぞや 今日の本当のお題である extglob という単語は拡張 extended glob の略です、多分。じゃ glob って何って言ったら、そりゃ Wikipedia でも参照してください。Wikipedia の当該エントリ曰く、"Global command" の略だそうです。

で、世間一般では、よく言われるのはワイルドカードってやつですね。POSIX だと、単に「パターンマッチング」とか呼ばれてるアレです。man 7 glob でもいけるかもしれません。あの、
*任意の0文字以上マッチ?任意の1文字にマッチ[c...]ブラケット内のいずれか1文字([a-z]のような範囲指定も可)にマッチ という、単純なやつです。で、こんなの拡張するぐらいだったら正規表現使えばいいじゃんと、世界中から総ツッコミが入りそうなところですが、シェルスクリプトでは "echo ファイル*" みたいなパス名マッチングだけでなく
${parameter%pattern}
case ... in pattern) ... と、それ以外にも Bash では
[[ str == pattern ]] とか pattern が使われるところがあるので、これを拡張すると他のLLは嫌いだけどシェルスクリプトの最新機能は好きとかいう偏食家に大いに受けるわけです。ちなみに最後のは、複雑なことをしたければ [[ str =~ regex ]] 使ってください、と言いたいところだけど例のごとく Bash は遅いので、sed とか awk, grep を使ったほうが無難です。
case文 簡単に。書式としては case WORD in
  pattern) expression;;
  pattern | p…

Base64 decoder - Bash Advent Calendar - Day 9

むか~し、このネタをどこかに書いた気がするので、既に見たことがあったらゴメンナサイ。何度も書くけどネタがないんです。ネタください。
Base64の仕様RFC3548読んでください。以上。だって、ここ読むような人は大体知ってるか、知らなくてもこの後読めば分かるでしょ。

では何なので、エンコーダーの場合

3 octet (24 bit, ASCII char 3 文字分) を 6bit のかたまり x 4 に展開各 6 bit を以下の文字に変換0 〜 25: "A" 〜 "Z"26 〜 51: "a" 〜 "z"52 〜 61: "0" 〜 "9"62: "+", 63: "/" 処理の最後、入力が 1 octet もしくは 2octet しかない場合には "=" で padding という感じで変換します。これでも意味不明なら、Wikipedia でもなんでも、適当に検索して自分で調べてね。 Bashの64進数 前回、基数が37以上の場合を説明しませんでしたが、下記64進数のマッピングから類推してください。で、64進数のマッピングは
0 〜 9: "0" 〜 "9"10 〜 35: "a" 〜 "z"36 〜 61: "A" 〜 "Z"62: "@", 63: "_"  となっております。そんなわけで、上のマッピングのの違いを吸収してあげるだけで、Base64デコーダーが算術式評価で簡単に作れる、はず。paddingとか面倒だけど。 検証用入力値 "Bash" AND "base64" で検索すると出てくる数々の、「コマンドライン上でBase64」を処理する方法。全然、Bash スクリプトじゃないじゃないか。そこですぐスクリプトが検索結果に出てきたらネタにならないんですけどね。
とにかく、検索したところ base64 コマンドを使えと。まんまですね。というわけで $ echo "Hel…

Misc - Bash Advent Calendar - Day 8

今までちょっと説明が足りなかったところのランダムな補足。正直、既に息切れなので小休止。

配列変数の展開 特定の要素に対する文字列展開は、普通の変数の文字列展開と一緒なので省略。

${var[@]:-str}
var が存在し1個以上あれば ${var[@]} に同じ、そうでなければ str になる。var の中身を見て、それが空白文字だったら str に置きかわる、という動作をするわけではない。

${var[@]-str}
var が存在し1個以上あれば ${var[@]} に同じ、そうでなければ str になる。中身がない空の配列でも str に置き代わってしまうという残念な動作。仕様としては未定義っぽいけど。

${var[@]:?str}, ${var[@]:+word}
上と同様。

${var[@]:=str}
エラーになる。正直、エラーにならない場合、どんな動作をすべきか思いつかないので、妥当な仕様だと思う。

${var[@]:offset}, ${var[@]:offset:length}
offset 番目から length 個の要素を取り出す。実は同様に ${@:offset} とか ${@:offset:length} で、位置パラメータを部分的に取得できるんだけど、普通は shift 使えということで目にすることはまずないでしょう。残念ながら、各要素の部分文字列展開をしたい場合には、for ループで回すしかない。

${#var[@]}
配列の要素数になる。「各要素の文字列の長さ」が返ってくるわけではない。残念だけど、じゃぁ、配列の要素数を返すのに他に適当な記法があるかといえば、たしかにこれがベストと言わざるを得ないでしょう。

${var[@]#str}, ${var[@]##str}, ${var[@]%str}, ${var[@]%%str}
それぞれの要素に対して、先頭または末尾にマッチする文字列が削除、その結果を返します。

${var[@]/pattern/str}, ${var[@]//pattern/str}
それぞれの要素に対して、パターンにマッチした文字列を置換して、その結果を返します。

${var[@]^pattern}, ${var[@]^^pattern}, ${var[@],pattern}, ${var[@],,patte…

算術式(その2) - Bash Advent Calendar - Day 7

昨日の続き、算術式内の変数について。

数値インデックスの配列変数(連想配列じゃない方の配列)にも対応しています。なので
$ declare foo=(1 2 3)
$ declare -i bar="foo[0] + foo[1] + foo[2]"
$ declare -p bar
declare -i bar="6" これまでと同様、再帰的に算術式として評価されるので
$ declare foo=(0 1)
$ declare bar="foo[0] + foo[1]"
$ declare -i buzz
$ buzz="bar[0] + bar[1]"
$ declare -p buzz
declare -i buzz="3" これで何が嬉しいのか書いてる本人もよく分かりませんが、とりあえずこんなこともできますよと。
基数#文字列 これで昨日のリストの1〜4を説明しました。6は単純な数値なので、これで最後、今日のメインディッシュ "基数#文字列" です。

これまでに説明した8進数、16進数、そして普段使いの10進数以外に使いそうなのは2進数ぐらいですかね。
$ declare -i foo
$ foo="2#10100101"  # 0xA5
$ declare -p foo
declare -i foo="165" これまで同様、何が嬉しいのかよくわからないですね。

11進数から36進数までは数字とアルファベット(大文字、小文字の区別なし)で数値を表現します。すなわち
$ declare -i foo
$ foo="36#sekine"
$ declare -p foo
declare -i foo="1717524842" 36進数とか言われても、これで正しいかどうなのかよく分からんですね。せっかくなのでこれまでの算術式やら、配列など色々駆使して、この値を検証してみましょう。
$ char_code_hex=($(echo -n 'asekine' | od -A n -t x1))
$ declare -i -a char_code_hex…

算術式 - Bash Advent Calendar - Day 6

Array, Associative Array と予定どおり A から順にネタを消化中で、今日は Arithmetic Expression。辞書順的に後戻りですが、細かいことは気にしないでいきましょう。
扱える範囲 とりあえず小数は扱えません。小数を使うような計算が必要なときは素直に他のLLを使いましょう。

扱える整数の範囲は実装依存で、いわゆる long の範囲です。最近の 64bit 環境であれば -2^63 〜 2^63 - 1 なので、十分実用に堪えると思います。
算術式が使われる場所 ちゃんとチェックしてないので抜けがあるかもしれませんが

数値変数への代入 (local, readonly, declare, typeset コマンドを含む)let "算術式"((算術式))for ((算術式; 算術式; 算術式)) do ... done$((算術式))  ($[算術式] もいまだに使えると思いますが、そのうち使えなくなるはず)配列変数[算術式] や ${配列変数[算術式]} などの配列変数のインデックス。部分文字列展開: ${変数:算術式} および ${変数:算術式:算術式}数値比較 [[ 算術式 OP 算術式 ]] (OP は -gt, -ge, -lt, -le のいずれか)
ぐらいですかね。最後のは undocumented なので、期待したとおりに動かなくても当方は関知いたしません。
数値変数 説明の都合上数値変数の定義だけ。

declare -i で変数を数値変数として定義できます。
$ declare -i foo=1
$ declare -p foo
declare -i foo="1" declare -p の結果の右辺が "1" とクォートされているので文字列っぽく見えますが、ここはそういうものだと(今日のところは)思っててください。declare の後にちゃんと -i と付いているので、これは確かに数値変数です。

ちなみに、配列 / 連想配列とは直行する概念なので
$ declare -ia foo
$ declare -iA bar
$ declare -p foo bar
declare -ai foo='()'
declare -Ai bar=…

連想配列 - Bash Advent Calendar - Day 5

今日は連想配列についてです。なんか予想以上に読者が少なくてモチベーションが上がりません。
初期化 基本的な書式は数値インデックスの配列(以下「普通の配列」)と変わりません。declare で指定する引数が大文字の A になるぐらい。
$ declare -A foo
$ declare -A foo=() ただし、普通の配列の場合にはインデックスを指定しない場合には 0 から順に勝手にインデックス値を決めてくれましたが、(ある意味当然ですが)連想配列の場合は必ずインデックス文字列が必要です。
$ declare -A foo=("bar" "baz")
bash: foo: bar: 連想配列を設定するときには添字をつけなければいけません
bash: foo: baz: 連想配列を設定するときには添字をつけなければいけません というわけで、 $ declare -A foo=(["bar"]="BAR" ["baz"]="BAZ")
$ declare -p foo
declare -A foo='([bar]="BAR" [baz]="BAZ" )' でメデタシメデタシとなります。
一つ普通の配列と違うことは、declare 文(または typeset)が省略できないことです。 $ unset foo bar baz
$ foo=(["bar"]="BAR" ["baz"]="BAZ")
$ declare -p foo
declare -a foo='([0]="BAZ")' 一見すると意味不明かもしれませんが、これについては後述します。Bash の仕様としては、宣言されてない変数に対して配列を代入しようとした場合、それは常に普通の配列として初期化されるということになります。 値の代入、追加 細かいところはDay 1での説明を参照してください。常にインデックスが必要な以外は普通の配列と一緒です。+= の糞仕様も健在です。 $ declare -A foo=(["bar"…

配列操作の性能 - Bash Advent Calendar - Day 4

昨日まで配列について説明してきましたが、残念なお知らせです。

遅い、とにかく遅い。私が初めてこの機能を知った時、これで多くの場面で sed, awk が要らなくなり、fork() しなくてすむことによりスクリプトが高速になるのではないかと思いました。で、試しにとあるスクリプトを書き換えてみたのですが、むしろかなり遅くなってしまいました。

bash, ksh, zsh の速度比較 - 拡張 POSIX シェルスクリプト Advent Calendar 2013でも述べられている通り、bash さん遅いんです(配列操作に限りません)。ここで bash と他のシェルを比べた時に、他のシェルに負けると悔しいので、AWK と対決。
#!/bin/bash
DICT=/usr/share/dict/american-english
declare -a english_words
declare dict_content
function load_dict() {
  local IFS=$'\n'
  dict_content="$(< ${DICT})"
  english_words=(${dict_content})
  readonly dict_content english_words
}
function replace_st_to_ts() {
  local unused=("${english_words[@]//st/ts}")
}
function now() {
  date +%s.%N
}
load_dict
start=$(now)
for ((i=0;i<10;i++)); do
  replace_st_to_ts
done
end=$(now)
echo -n "Bash: "
bc -l <<< "${end} - ${start}"
start=$(now)
for ((i=0;i<10;i++)); do
  awk '{gsub(/st/, "ts"); print}' <<< "${dict_content}" > /d…

配列(その3) - Bash Advent Calendar - Day 3

すでに3日めにして当初の勢いは全くなし。このままずっと続く気がしません。

閑話休題、変数展開との組み合わせで面白いことできるんじゃないの的なお話。
変数展開 普通の変数展開については既に知ってる前提で。で、配列変数においても変数展開が可能です。

まずは特定要素の変数展開をば。
$ foo=("bar" "baz")
$ echo "${foo[0]:-qux}"
bar
$ echo "${foo[2]:-qux}"
qux と期待通りの動作をしてくれます。デフォルト値の設定も同様に
$ foo=("bar" "baz")
$ : "${foo[2]:=qux}"
$ declaare -p foo
declare -a foo='([0]="bar" [1]="baz" [2]="qux")'
$ : "${foo[1]:=quux}"
$ declaare -p foo
declare -a foo='([0]="bar" [1]="baz" [2]="qux")' と期待通りの動作ですね。

その他にも ${var:?word} ${var:+word} も同様に想像通りの動作をしてくれます。
応用編 特定要素ではなくインデックスに @ を指定して変数展開をすると、文字列処理が一気に出来ます。Python ユーザーあたりにはウケがよさそうな $ foo=("bar" "baz")
$ qux=("${foo[@]//a/A}")
$ declare -p qux
declare -a qux='([0]="bAr" [1]="bAz")' みたいなことができてしまいます。これは配列の各々の要素において "a" を "A" に置換しています。このように for ループ無しで一気に文字列を処理できます。
これって Python で…

配列(その2) - Bash Advent Calendar - Day 2

すでに時間ギリギリ。さて、昨日は初期化と代入を説明したので、今日は削除と参照をば。
削除 変数まるごと削除は unset で。
$ foo=("bar" "baz")
$ unset foo
$ declare -p foo
bash: declare: foo: 見つかりません
特定の要素を削除するには unset 変数[インデックス]で。
$ foo=("bar" "baz")
$ unset foo[0]
$ declare -p foo
declare -a foo='([1]="baz")'
削除については以上。よほど大規模な Bash スクリプトでもない限り、unset とかわざわざ使うこともないでしょう。
参照 これだけでかなりの量を書ける気がするのですが、二日目にして既に息切れ状態なので手短に。
もう日本語が面倒になってきたので、以下の例参照。 $ foo=("bar" "baz")
$ echo ${foo[0]}
bar
$ echo ${foo[1]}
baz
$ echo ${foo}
bar
$ unset foo[0]
$ echo ${foo}
    # 何もなし というわけで、${変数[インデックス]} で参照できます。インデックスを省略した場合、それは [0] と等価(最小インデックスを参照してくれるわけではない)になります。どうがんばって見ても、インデックス指定なしの参照は配列変数にアクセスしているようには見えないので、変に省略するのはやめましょう。もとい、そんな変な仕様知ってる人なんてほとんどいないでしょう。 すべての要素を参照 ここまではウォームアップです。これから実用性アップのはず。
さて、配列にまとめてアクセスするには * もしくは @ という特殊なインデックスを使います。 $ foo=("bar" "baz")
$ echo "${foo[*]}"
bar baz
$ echo "${foo[@]}"
bar baz この例では * と @ に違いがありませんが、その違いは "$*" と "$…

とあるインフラエンジニアの独り言

SlideShareのスライドをダウンロードできるサイトを作りました。」の件を肴に、ちょっと独り言。

端的に言えば、ある人が「SlideShare がスライドダウンロードさせてくれないからダウンローダー作ったよ」とおっしゃってますが、それどうなのよ、から派生してスクレーパーとかマジやめてというお話。 規約の内容 まずは SlideShare の規約がどうなってるかですが、Terms of Service に You agree not to use or launch any automated system, including without limitation, "robots," "spiders," "offline readers," etc., that accesses the Site in a manner that sends more request messages to the SlideShare servers in a given period of time than a human can reasonably produce in the same period by using a convention on-line web browser.  と書いてあります。てきとーに意訳すると、 人間が一般的なブラウザを使った場合に送るリクエストよりも早いペースでリクエストを送る「ロボット」や「スパイダー」、「オフラインリーダー」といったような自動化されたシステムを使用しない、または立ち上げないことに同意します。 ってところでしょうか。後続の文では検索エンジンのロボットに対する条件が書いてありますが、このダウンローダーは該当しないので割愛します。

ダウンローダーは規約違反? 世の中には次に読むであろうページのプリフェッチ、さらにはプリレンダリングまでするブラウザが存在するらしい、というかそんな自社製品があるような気がするので、"human can reasonably produce" すなわち普通の人間がブラウザを操作することによって要求しうる QPS は一般人が思ってるよりは大きいのですが、当該サイトがその妥当性を考慮してダウンロードリクエストの…

配列 - Bash Advent Calendar - Day1

毎日続くかどうかわかりませんが、できる限り続けていきたいと思います。

さて、何から書いていいかわからないので、とりあえず最初は A から始まる単語はないかと探してみたところ、alias, array, associative array, argument, arithmetic evaluation と、とりあえず数日はいけそうな感じ。

というわけで今日は配列について。
まず注意点として、配列は sh にはない Bash 独自の機能です。なので #!/bin/sh で書き始めてあるスクリプト内で使うと、後々困ることがあるかもしれなので要注意。そもそも /bin/sh が Bash ってどうなのという議論は勝手にやりたい人だけがしてください。 変数の宣言、初期化 ちょっとかしこまった宣言 普段目にすることはあまりないかもしれませんが、C 言語出身者が好むスタイル(偏見100%)。 $ declare -a foo これで変数 foo は配列変数になります。
変数には初期値を入れた明示的な初期化が必要と考える、gccマンセー、もしくはC++出身者であれば(これも偏見100%、以下同じ) $ declare -a foo=() で、同じ中身が空の配列変数が宣言されます。
ちなみに、想像で適当に書いてるので、実際にこんな空の配列を使ってるのを見たことは一度たりともありませんw 値の代入による初期化 普通の変数の場合、わざわざ宣言などせず、いきなり値を代入しますよね。配列変数においても同じです。ある書式にのっとって値を代入すれば勝手に配列変数になります。 $ foo=("bar" "baz") 中身が実際にどうなってるかを確認したい場合には、 $ declare -p foo
declare -a foo='([0]="bar" [1]="baz")' というように declare -p を使いましょう。ちゃんと declare -a と配列変数になっているのが分かります。配列のインデックスもこれで確認できます。
さて、配列のインデックスが出てきたのでもう一つ。初期化時に、インデックスを指定することもできます。上の declare -p の出力から類推できるように、 $ foo=(…

アメリカのオンラインバンキング

なんか進化の方向が間違ってる。

相変わらずの小切手文化のまま IT 化が進んでます。この前銀行にの窓口に用があって行ったのですが、となりの窓口のにーちゃんがしきりに「スマホでできるよ、写真をとってうんたらかんたら」と顧客に説明してました。

話からして多分小切手の換金ができるんじゃないかな、そういえば俺も換金してない小切手があったなとスマホアプリをインストール、小切手の換金ができるかどうか試してみました。

小切手をそのアプリ内の写真機能で撮ると画像認識処理が走り、やれ枠内に収まってないとか、裏書きが認識できないとか教えてくれます。そしてちゃんとした写真が撮れると前に進めて、やっとアップロード完了。多分処理時間からして、小切手の発行元の口座番号あたりは事前に判別してそうな感じです。スマホアプリも進化したね。

でも、なんか日本での感覚からするとおもいっきり何かが間違ってる感じがします。普通に振り込んでくれればいいんじゃないかと。システムとか手数料体系が小切手文化に合わせてあるっぽいので、振込の方が手数料が高そうだけど、明らかに小切手を使ったやり取りのほうが人的コストが掛かってるよね。

きっと何年も住んでるうちに慣れてしまうのだろうけど、今の時点では何かおかしなことをやってる感がぬぐえません。

Raiders完敗

MNF は地区内ライバルのデンバー戦でしたが、P. Manning はファンブルロスト以外ほぼ完璧、なすすべなしでした。T. Branch 一人欠けたからとかそんなレベルじゃなかったようです。おまけに D. McFadden のランも完全に封じられて攻守ともに完敗です。

相手は3戦全勝で早くも地区優勝は厳しい感じなので、後はワイルドカード争いに加われるかというのがポイントになってくるかと思います。

NFL 2013-2014 シーズン開幕

NFLって書いたけど、Raiders以外のはノーチェックです。

さて、我らがRaidersは残念ながら黒星発進です。最後まで惜しかったですが、Red Zoneで2度もインターセプトされてたら勝てる試合も勝てません。

さて、次週は Jaguarsとの対戦なのですが、いきなりリーグ最下位決定戦とか言われています。というのもESPNのランキングで我らがRaidersがブービーの31位、そして相手のJaguarsがドベの32位だからです。

どうせ弱いなら負けに負けまくって、来年のドラフトで頑張るしかないですね。

ブログの見た目をちょっと変更

Google+への統合が進んだらしいので、設定見直しのついでにゴテゴテとガジェットを追加してみました。

とりあえず上部にある検索バーが超絶カッコ悪い気がしますが、とりあえずはこのままでいこうかと思います。

免許取れました

今日は Redwood City の DMV で実技試験を受けてきました。10:30の予約で10:15に受付、1時間待って11:20からやっと試験。さらっとスケジュール表を(盗み)見た感じ、10:30(からの30分)の予約枠には6人いたようですが、試験官が2人で試験に30分かかります。何かがおかしい。さらに、試験官2人は車体検査の担当を兼務しているみたいで、かつそっちの方がが優先のようです。私は同じ予約枠の中では2番目ぐらいでこの有り様なので、同じ枠の最後の人は12:30ぐらいからテストだったんじゃないでしょうか。

さて肝心の試験ですが、試験官は母親が日本人で本人も日本に20年住んでたとかで日本語ペラペラ。試験の説明書も英語/日本語の2か国語バージョンでした。ペーパーテストが日本語で受けられるのは知ってましたが、実技試験も頼めば日本語でできるのかもしれません。

もとい、私は特にリクエストしたわけじゃないのですが、名前がどっからどうみても日本人ということで「英語と日本語のどっちがいい?」と聞かれました。実技試験という他に頭を使う余裕があまりない状況ですので、「日本語でお願いします」と即答しました。

この日本語を話せる試験官のおかげで大変助かりました。正直、英語で試験してたら落ちてたかもしれません。他の州は知りませんがカリフォルニでは15点減点まではOKなのですが、なんとか10点減点で収まり無事合格です。

なお、その10点減点のうち7点は停止時の前の車との車間の短さと一旦停止時の停止線までの距離の短さでした。言い訳をすると、急遽前日に車が変わったのでブレーキが(前の車と比べて)効きにくかったんです。それは分かってたことなのでもうちょっと気をつけるべきだったのですが、予想外に減点されてました。残りは車線変更での後方確認不備(もっとちゃんと首振って確認しろ)が2回と、後退時の後方確認不備でした。

ちなみに縦列駐車はなかったです。戦々恐々としてたのに拍子抜けです。英語で試験、かつ縦列駐車のチェックがあったら試験に落ちてたと思います。

レンタカーで運転免許試験を受ける予定

さて、国土が広いアメリカでは車が必須なわけでして、このたび運転免許の実技試験を受ける予定です。この実技試験、日本との一番の違いは自分の持ち込んだ車で試験の受けることです。慣れた車で試験を受けられるっていいですよね。日本と違い、身分証代わりにとりあえず取っておくなんてことはないので、家族の誰も車を持ってないのに免許を取るなんてシチュエーションはそうそうないんでしょう。

で、当初の予定では、実技試験を受ける頃には新車を既に購入しているはずだったのですが、なんだかんだでまだ自分の車がありません。そんなわけで渡米後から借りてるレンタカーを延長し、そのレンタカーで試験を受けることになります。

さて、ここで問題発覚。なんといわゆる車検証がありません。実技試験に車を持ち込むにあたっては車検証と自賠責が必要なんですが(追記を参照のこと)、そういえば自賠責の保険証もないよ!

というわけで期限延長の電話をしたついでに「車検証ないけどどうしたらいいのさ」って聞いてみたところ、「借りたとこに行ってね」という素晴らしいお返事が。うそーーーーーーーーーーーーーーーーん、車を借りたのはSFO空港なんですけど。

そんなこんなで今日はSFOまでドライブしてきました。ここでも色々あって2時間ぐらいかかったんですが、もう書く気力もありません。

とりあえず教訓としては借りるときにちゃんと確認しておくと。それと、レンタカーの窓口で車を実技試験に使うとちゃんと申告しておくことです。自賠責の保険証も今は手元にあるのですが、「借主はこの車の自賠責保険でちゃんとカバーされますよ」的な手紙を貰えました。この手紙はレンタカー会社の支店ならどこでも発行してくれるとは思いますが、最初に貰っておいて損はないでしょう。

ちなみに、まだ解決されてない問題がありまして、明日は朝からまた近所のレンタカー屋さんですorz

[追記]
その後、今度は車が故障して車体交換したのですが、やっぱり車検証(vehicle registration)がない。でそれじゃ困るって話をしたら Hertz の優しいお兄さんがどこかに電話して確認してくれました。曰く、保険に入ってる証明書さえあればレンタカーはOK(ただし、ライセンスプレートがちゃんとしてること)だよと。実際、大丈夫でした。

結論としては、何はなくとも「使用者は車の保険でカバーされます」とい…

UnionBankで小切手帳取得までの長い道のり

うちの会社の場合、会社の近くにある銀行ならSSNなしでも簡単に口座が開設できますし、事前にそれは知っていました。

が、送金手続きなどの都合上、渡米前に口座番号を確定したかったので三菱東京UFJ系列のUnionBankに口座を開設しました。日本語で対応してくれるコールセンターがあるのもポイントです。

日本にいる間に口座の開設済ませ、渡米前にキャッシュカードも取得。これには少し時間がかかるので、もしUnionBankにしようとする人は早めに行動しておいたほうがいいと思います。

あとは、渡米後にどこかの支店に行ってキャッシュカードの有効化と小切手帳の発行をお願いすることになります。

仮住まいに到着後、何はなくともお金はいるよねってことで一番近いUnionBankでキャッシュカードの有効化、そして小切手帳をお願いしました。

ところがこれまたトラブル発生。「小切手帳は住所がアメリカじゃないと発行しないよ。とりあえず住所変更は受け付けるので、1営業日待ってまた来るかコールセンターに電話してね」と。そんな面倒なこと、最初の資料になかったのに。

というわけで何日か経ってコールセンターに電話してみました。前記のとおりせっかく日本語で対応してくれるので、そっちに電話。するとまだ住所変わってないのでとあと1週間ぐらい待ってみてください。ナニソレ。

で、また1週間待って電話してみました。やっぱり住所が変わってないので、結局電話で住所変更の申請。ナンダヨソレ。

また待ってと言われても面倒なので、そこから1週間我慢して、今度は最初に行った支店へ。で、住所を確認してもらったらまだ日本のまま。ドウナッテンダヨー。

支店の窓口で対応してくれた人は前回と同じ人だったのですが、「あなたの住所変更したのは覚えてるわ。おかしいわね、ちょっと待って。。。」とわざわざマニュアルを確認しながら再度入力。でもなんかうまくいってないみたい。

たまたまシニアっぽい人がいたのでその人にヘルプを求めます。すると「SSNの登録か、もしSSNがまだなら入国の証明とIDの確認がないと海外からの住所変更はできないのよ」と。ナンダッテー。

というわけでSSNの番号を教えたらやっとこさ住所変更はできました。小切手帳はそのうち送られてくるそうです。

とりあえず、窓口の人が触ってたシステムだと住所変更が失敗しても画面ではよくわからない様…

I-94 が電子化されたけど

皆様こんにちは。

アメリカにビザ持ちで入国するときに記入が必要だったI-94が電子化されました。僕は電子化された直後にアメリカに来たのですが、DeltaのCAはまだ電子化のことを知らなかったみたいで、わざわざ紙のI-94を機内で書きました。せっかく書いた紙のI-94は入国審査時に目の前でビリビリに破かれました。

さて、I-94 が電子化されたのなら、従来言われていた「SSNの申請は入国してから10日ぐらい経ってからじゃないとデータがないって追い返される」というのはもうないんじゃないか、ということで入国4日後に SSA オフィスに行ってみました。

すると何やら画面を操作して手続きを進めてる様子。これはすんなり行くかと思ったらまさかのどんでん返し。「DHSに登録されてる誕生日とお前のパスポートの誕生日が違うからダメ」と。意味わかんねーよ。どうすりゃいいのよと聞いたところ「DHSに登録されている情報が修正されるのを待て。もしダメだったら手紙が行くからね」と。

最終的にはそれから10日後ぐらいに郵便で届きましたが、やっぱり10日ぐらい経ってから行ったほうがよかったのかもしれません。

転勤のご挨拶

このたび5月13日付けでアメリカ Google Inc. の Mountain View 本社で働くことになりました。 Google 日本法人は退社という形になるので、世間一般で言う転籍にあたるかと存じます。

皆様には、今まで公私にわたり大変お世話になり感謝しております。インターネットに国境なんて無いし、毎年1回ぐらいは帰国する予定でいるので、これからも変わらずお付き合い出来るかと思います。というわけで、これからもよろしくお願いいたします。

取り急ぎご報告まで。

(追記) いわゆる栄転じゃありません。うちの部署の性質上、転勤できる場所が限られているのでたまたま本社になっただけです。

やっぱり基礎って大事だよね

はじめに 元ネタ「プロセス間の期限付き排他ロック」が前の記事と一緒ですが、誰かを貶めたり中傷しようとしたりというのではなく、勝手に上から目線で「基礎知識が足りてないよね」とミサワ的な発言をすることを目的とした記事となっております。ご承知ください。
仕様のここがまずそう 「実装」のセクションに書いてある
シンボリックリンクを使って排他制御する 期限切れは、シンボリックリンクそのものの mtime で表現するmtime <= now なら期限切れつまり、シンボリックリンクの mtime を期限が切れる時刻(未来)にする
ですが、「ロックとは何か」とか「アトミックな操作とは何か」あたりの基礎知識がある人にとっては、ちょっと考えればまずいのがすぐに分かります。シンボリックリンクの作成symlink(2)とmtimeの変更utimeutimensat(2)は別々のシステムコールであり、両者をアトミックに行えるシステムコールがありません。
すなわちsymlink(2)が成功したとして、その次にutimeutimensat(2)が実行されるまでの「間」というものが存在し、その間に他のプロセスが色々するチャンスがあるわけです。特に、作成されたシンボリックリンクはutimeutimensat(2)が実行されるまでは「期限切れ」状態にあるとみなせます。その結果、utimeutimensat(2)の実行時点で持っているシンボリックリンクは競合するプロセスから見れば期限切れなので、そのシンボリックリンクは削除されてしまう可能性があるわけです。
この一点に関しては、symlink(2)でのリンク先としてTTLをセットするということで、期限が未来であるロックをアトミックな操作で作成できます。しかし、期限切れのロックファイルをどう取り扱うかという点にも問題があるので、そう簡単にはいかないというのは元記事のコメント欄にあるとおりです。
ちなみに、その期限切れロックファイルの扱いの問題を同じようにシステムコールレベルで見れば、statlstat(2)とunlink(2)をアトミックに実行することはできない(ので、その為に別のロック機構が必要になっちゃう)よねってな話になるかと思います。 もったいない さて超上から目線で偉そうですが、「知識が足りないのってもったい無いよね」というのが元記事に対…

関数名は大事だよね

プロセス間の期限付き排他ロックについて。

既にコメントが付いてるので、設計レベルでどうだとか、というのはおいておきます。

とにかく実装をパッと見て、これはダメそうだなというのは
52 sub lock {
中略
62             $self->unlock;
63         }
64     }
65     if (symlink $target, $self->file) { あたりで気づけるのではないでしょうか。lock関数の中で、実際にlockを獲得しているのが65行目のsymlinkなのに、その手前でunlockを呼んでます。一般的に言って、獲得してないロックを解放するのはかなりまずいでしょう(実際、このunlockの呼び出しの直前で他のプロセスがlockに成功すると、そこで生成されたロックファイルを勝手に削除しちゃうことになり、結局2重にlockが獲得できちゃいます)。
さて、標題の「関数名は大事だよね」ですが、unlockの実装は 73 sub unlock {
74     unlink $_[0]->file;
75 } だけなので、下手するとunlinkってな名前を付けちゃいそうです。が、実装がたまたまそうなってるだけで、呼び出し側から見ればやりたいことはunlockなのですから、この名前で大正解。これがunlockと命名されていたからこそ、lock関数の実装がダメそうなのがすぐに分かったわけです。
というわけで、関数名を横着しないできちんと付けてると、コードの間違にも気づきやすいよねというお話でした。