ソースコード - みる会図書館


検索対象: Shell Script ライトクックブック
73件見つかりました。

1. Shell Script ライトクックブック

121 果の住所欄への入力を担当する JavaScript だ。そして、受け取った 7 桁の郵便番号から辞書を引き、得られた 住所文字列を返すシェルスクリプトが "zip2addr. ajax. cgi" である。 名前を見ればわかるがこのシェルスクリプトも Ajax として動作するので、レシピ 4.6 ( Ajax で画面更新し たい ) に従って部分 HTML を返してもよいのだが、 こでは敢えて JSON 形式で返すことにした。「もちろん JSON で返すこともできる」ということを示すためだ。 JSON で返せば、例えばクライアント側で何らかの汎用 JavaScript ライプラリーを利用していて、それと繋ぎ込むといったことも可能というわけだ。 ソースコード 概要が掴めたところで、主要なソースコードを記していくことにする。 アプリケーションの中身を、とくと堪能してもらいたい。 尚、これらのソースコードは GitHub でも公開している * 3 。 ■ data/mkzipdic-kenall. sh ー辞書ファイル作成 ( 一般地域名用 ) シェルスクリプトで構成された Web このプログラムは、 Web サイトから ZIP ファイルをダウンロードして展開する都合により、 POSIX 非準拠 の curl コマンドと unzip コマンドを必要とすることを御了承願いたい。 # ! /bin/sh ・成功時には辞書ファイルを更新する。 しの場合は 0 、失敗したら 0 以外 ー作成成功もしくはサイトのタイムスタンプが古いために作成する必要無 ・戻り値 # [ 出力 ] 今ある辞書ファイルより新しくても更新する ・サイトにある csv ファイルのタイプスタンプが、 # Usage : mkzipdic . sh —f # 日本郵便公式の郵便番号住所 csv から、本システム用の辞書を作成 ( 地域名 ) # MKZIPDIC_KENALL . SH # 初期設定 # ーー一変数定義ー cd "$d"; pwd)" # この sh のパス readonly ur1-ZIPCSVZIP=http : //www.post ・ japanpost. jp/zipcode/dl/oogaki/zip/ken-all. zip # 郵便番号辞書ファイルのパス readonly fi1e—ZIPDIC="$dir_MINE/ken_a11. txt" readonly f1g—SUEXECMODE=0 * 3 https ://github.com/She11Shoccar—jpn/zip2addr # 日本郵便郵便番号ー住所 # csv データ (Zip 形式 ) URL # サーバーが suEXEC モードで # 動いているなら 1 を設定

2. Shell Script ライトクックブック

利用者の陰に潜む、様々な落とし穴 34 $ seq 1 10 ー gsed ' 3 , + 3N ; 1 2 9 10 これはおかしい ! 第 2 章 でも一部の文字が化けてしまう。どうすればよいか。ただし、標準入力は他のデータを渡すのに使っており、 AWK に値を渡したいのだが、 -v オプションで渡しても、シェル変数を使ってソースコードに即値を埋め込ん 問題 レシピ 2.6 標準入力以外から AWK に正しく文字列を渡す つかるかもしれない。 sed で N コマンドを使っているソースコードでもしおかしな動きをしていたら、 sed を疑ってみると原因が見 は執筆時に取得できた最新版 ( 4.2.2 ) でも残っていた。 やはりおかしい。 3 行目から十 3 行目までだから 7 行目と 8 行目が結合されてはいけないはずだ。ちなみにこれ 使えない。 awk —v "s=$str" 'BEGIN{print s} ' means awk ' BEG 工 N{print 回答 ←渡したい文字列 ← \ n がうまく渡せない ← *n も一 " もうまく渡せない ( 工ラーにもなる ) 環境変数として渡し、 AWK の組込変数 ENVIRON で受け取る。問題文の "*n means ー いのであれば、 こう書けばよい。 str='*n means "newline" ' awk 'BEGIN{print ENVIRON["str"] } ' newline ー ”を渡した 既にシェル変数に入っているのであれば export して環境変数化してから渡してもいいし、それが嫌ならコマン ドの前に仮の環境変数 ( 例えば "E ” ) を置いて渡したり、 env コマンドで渡してもいいだろう。

3. Shell Script ライトクックブック

レシピ 1.3 grep に対する fgrep のような素直な sed それを置換後の文字列として指定してやればよい。 改行で終わる文字列の入ったシェル変数を作る そのシェル変数を作る際、次のように即値で記述することもできる。 3 しかしこれでは結局、ソースコードを綺麗に書くという目的の達成はできていない。そこで、 printf コマンド を使って“ \ ”と改行コード (<0xOA>) の文字列を動的に生成し、それをシェル変数に代入するのだが、直接代 入しようとすると失敗する。それは、コマンドの実行結果を返す“ $ ( ~ ) ”あるいは“ ( 果の最後に改行があるとそれを取り除いてしまうからだ。 ' という句が、実行結 取り除かれないようにするには、改行コードの後ろにとりあえずそれ以外の文字の付けた文字列を生成して代 入してしまう。そして、シェル変数のトリミング機能 ( この場合は右トリミングの“ % ” ) を使い、先程付けてい た文字列を取り除いて再代入する。この時は“ $ ( ~ ) ”句を使っていないから、文字列の末尾が改行であっても 問題無く代入できるのである。 シェル変数を sed に混ぜて使う場合の注意点 こで作ったシェル変数を用いて今回の置換処理を記述する時、 と書かないように注意。 $ LF をダブルクオーテーションで囲まなければならない。ダブルクオーテーションで囲 まれなかったシェル変数は、その中に半角スペースやタブ、改行コードがあるとそこで分割された複数の引数が あるものと解釈されてしまう。つまり、 "s/**n/* ”と“ / g ' が別々の引数であると解釈され、エラーになってし まうからだ。 これは sed に限った話ではないので、コマンド引数をシェル変数と組み合わせて生成する時は常に注意する レシピ 1.3 grep に対する fgrep のような素直な sed 問題 シェル変数に入っている文字列に置換されるマクロ文字列を定義し、それをテキストファイルの中に配置し たい。 sed コマンドを使おうと思うのだが、シェル変数にはどんな文字が入っているのかわからない。つまり sed の正規表現で使うメタ文字が入っている可能性もあるので、単純にはいかない。 回答 sed がメタ文字として解釈しうる文字を予め工スケープしてから sed に掛ける。具体的には次のコードを通す ことで安全にそれができる。置換前の文字列 ( マクロなど ) が入っているシェル変数を $ fr 、置換後の文字列が 入っているシェル変数を $to とすると、

4. Shell Script ライトクックブック

58 」 SON にエスケープ文字が混ざっている場合 第 3 章 POSIX 原理主義テクニック JSON は、コントロールコードや時にはマルチバイト文字をエスケープして格納している事がある。例えば "*n' や "*t ”はそれぞれタブと改行文字であるし、 "*uxxxx ” (XXXX は 4 桁の 16 進数 ) は Unicode 文字であ る。このような文字を元に戻すフィルターコマンド "unescj. sh" も同じ場所にリリースした * 7 。 詳細な説明は parsrj. sh と unescj. sh のソースコード冒頭に記したコメントを見てもらうことにして割愛す るが、 parsrj. sh で解読したテキストファイルをパイプ越しに unescj. sh に与えれば解読してくれる。もちろん unescj. sh も POSIX の範囲で書かれている。 解説 CSV がパースできたのと同様に、 JSON のパースも POSIX の範囲でできる。本章の冒頭で述べたことだが、 POSIX に含まれる sed や AWK はチューリングマシンの要件を満たしているのだから、それらを使えば理論的 にも可能なのだ。 CSV の時と同様、 JSON にも値の位置を示すための記号と、同じ文字ではあるものの純粋な 値としての記号があるが、冷静に手順を考えればきちんと区別・解読することができるのだ。とは言うものの具 体的にどのようにして実現したのかを解説するのは大変なので、どうしても知りたい人はソースコード読んでも こでの説明は割愛する。 らうことにして、 しかし、 JSON パーサーとしては。。 jq ”という有名なコマンドが既に存在する。にもかかわらず、筆者はなぜ こちらのコマンドなら POSIX 原理主義に基づいているため、「どこでも動く」「コン 再発明したのか。確かに パイルせずに動く」「 10 年後も 20 年後も、たぶん動く」の三拍子が揃っているという利点もあるのだが、真の 理由はまた別のところにあったので、ここで語っておきたい。この後のレシピで XML パーサーを作った話を述 べるが、同様の理由であるのでまとめて語ることにする。 」 SON & XML パーサーという「車輪の再発明」の理由 jq や xmllint 等、 UN Ⅸ哲学に染まりきっていない シェルスクリプトで、 JSON を処理したいといったら jq コマンド、 XML を処理したいといったら xmllint や hxselect (html-xml-utils というユーティリティーの 1 コマンド ) 、あるいは MacOSX の xpath といったコマ ンドを思い浮かべるかもしれない。そして、それらは「便利だ」という声をちらほら聞くのだが、私はちっとも 便利に思えない。試しに使ってみても「なぜこれで満足できる ? 」とさえ思う。理由はこうだ。 ー理由 1. ーっのことをうまくやっていない UNIX 哲学の一つとしてよく引用されるマイク・ガンカーズの教義に 1. 小さいものは美しい。 2. 1 つのプログラムには 1 つのことをうまくやらせよ。 というものがある。しかし、まずこれができていない。 jq や xmllint 等は、データの正規化 ( 都合の良い形式に 変換する ) 機能とデータの欲しい部分だけを抽出する部分抽出機能を分けていない。むしろ前者をすっ飛ばして 後者だけやっているように思う。 でも UNIX 使いとしては、部分抽出といったら grep や A Ⅵ TK を使い慣れているわけで、それらでできるよ うにしてもらいたいと思う。部分抽出をするために、 jq や xm Ⅲ nt 等独自の文法をわざわざ覚えたくないし。 https ://github.com/She11Shoccar-jpn/Parsrs/b10b/master/unescj ・ sh * 7

5. Shell Script ライトクックブック

16 の後に 解説 ー awk {print $ 1 } などを付け足せばよいので簡単だ。 第 1 章 ちょっとうれしいレシピ 間題文にもあるが、日本の祝日は、その全てを計算で求めることができない * 7 。春分の日、秋分の日の二祝日 は毎年の天文観測によって二年後の月日を決めるように定められているからだ。計算で求められないことが明ら かなら、知っている人に聞くしかない。そこで WebAPI を叩くというわけだ。 いくつかのサイトが提供してくれているが、 Google カレンダーを使うのが手軽だろう。 iCalendar 形式 祝日情報をどういう形式で教えてくれるかというと、 iCalendar(RFC 5545 ) 形式である。 Google カレン ダー自体は独自の XML 形式や HTML 形式でも教えてくれるのだが、 iCalendar 形式はシンプルだし、きちん と規格化されているので、情報源を他サイトに切り替える可能性を考慮するならこの形式を選択しておくべきで ある。 iCalendar 形式の詳細についてはもちろん RFC5545 のドキュメントを見れば載っているし、日本語解説は野 村氏が公開している「 iCale Ⅱ dar 仕様」 * 8 が参考になる。ただ、例示したソースコードの説明に必要な項目だけは ' ーに記しておこう。 まず、この形式は HTML タグと同様にセクションの階層構造になっている。ただし、 HTML のようなタグ のインデントは許されず、タグ (HTML 同様、こう呼ぶことにする ) 名は必ず行頭に来る。 今回注目すべきセクションは "VEVENT ”でありここに祝日情報が入っているため、まずこのセクションの 始まり (BEG 工 N:VEVENT) と終わり (END:VEVENT) でフィルタリングする。今回は祝日の日付と名称が欲しい だけなので、それらが収められているタグ ("DTSTART ”と "SUMMARY ” ) 行だけになるよう、さらにフィ ルタリングする。あとは、 VEVENT セクションの中にあるこれら日付と名称の値を取り出して、 1 つ 1 つの VEVENT 毎に横に並べれば目的のデータが得られる。 Goog 厄カレンダーの URL ソースコードの中にもメモしているが、祝日一覧を返してくる WebAPI の URL は 2014 / 12 / 20 現在、次の ように辿れば見つけることができる。 G 。。 gle の都合によって将来移動する可能性もあるので、参考にしておい てもらいたい。 1 ) 2 ) 3 ) 4 ) 5 ) ログインして Google カレンダーを開く ( ただし最終的に得られた URL 自体はログインせず利用可能 ) ( 歯車マークアイコンの中の ) 「設定」メニュー 画面上部に「全般」「カレンダー」とある「カレンダー」タブ 「日本の祝日」リンク 「カレンダーのアドレス」行にある” ICAL ”アイコン 、 7 天文学データを入れれば「予測」することは可能だが、サーバー管理者にとって現実的な話ではない。 * 8 http : //www. asahi—net. 0 て . jprci5m—nmr/iCa1/ref . tml

6. Shell Script ライトクックブック

動作画面 実際の動作画面を掲載する。 尚、 デモペ 129 ージ * 4 も用意している。 郵便番号→住所検索 ax by シェルスクリプトデモ Perl or PHP or Ruby? WSOL or PostgreSOL? prototype. js or nuery? これくらいのことで、そんなの要らないよ。 もっと、和 UND< の力を活かそうせ ! 郵便番号 住所検索 実行 ! 住所 ( 都道府県名 ) 埼玉県 住所 ( 市区町村名 ) さいたま市浦和区 住所 ( 町名 ) 針ヶ谷 4 丁目 2 ー 20 住友生命浦 解説 + ソースコードを見てみる 図 6.1 住所補完アプリケーションの動作画面 使い心地 ( 速度 ) はいかがだろうか。ちなみに辞書データは地域と事業所を併せ、およそ 14 万件である。シェ ルスクリプトで開発したアプリケーションであっても、これだけの速度で動くということを実感し、「シェルス クリプトなんてプログラム開発には使えない」という思い込みは捨て去ってもらえれば大変うれしい。 * 4 http ://lab—sakura.richlab.org/ZIP2ADDR/public-htm1/

7. Shell Script ライトクックブック

レシピ 3.9 ひらがな・カタカナの相互変換 $ . /hira2kata 2 furigana. txt ロ 65 #No . い ろ は ほ フリガナ モガミ カガ フプキ ゼカマシ こうしておけば、全角カタカナで簡単に回答者名の grep 検索が可能になるし、 50 音順ソートもできるように なる。注意すべきは、この例では hira2kata コマンドの第 1 引数に“ 2 ”と書いてあるところである。これは、第 2 フィールドだけ変換せよという意味である。よって第 1 フィールドの数字はそのままになっている。仮に 2 という引数無しにファイル名だけ指定すると、フィールドという概念無しに、テキスト中にある全てのひらがな を変換しようとする。よって、その場合第 1 フィールドの「いろは・・・・・・」もカタカナになる。 尚、この hira2kata コマンドは UTF-8 のテキストにしか対応しておらず、 JIS や ShitfJIS 、 EUC-JP テキ ストには対応していない。そのような文字を扱いたい場合は、 ico Ⅱ v コマンドを用いたり、Ⅱ kf コマンド (POSIX ではないが ) を用いて予め UTF -8 に変換しておくこと。 それから、このサンプルデータで「ほ」行の島風さんだけ右から書いてあるが、こういうのはどーしよーもな い ! 昭和じゃないんだから左から書くように言っておいってもらいたい。 カタカナ→ひらがな変換コマンド "kata2hira" 上の例ではカタカナに統一したが、逆にひらがなに統一してもよい。その場合は "kata2hira ”という名のコマ ンドを使う。これも、 321516 氏が USP 研究所の OpenuspTukubai というシェルスクリプト開発者向けコマ ンドセット * 17 にある han 、 zen コマンドのインターフェースに似せる形で、 POSIX 範囲内で作ったものである。 あわせてダウンロード * 18 しておくとよいだろう。 解説 前のレシピで全角文字を半角文字に変換するコマンドが作れたのだから、半角文字に変換する代わりにひらが な・カタカナの変換をするのも大したことはない。 マルチバイト文字なので、半角・全角変換と同様に、 1 バイトずつ読んだ場合、それがマルチバイト文字の終 端なのか、それとも途中なのかということを常に判断しなければならないのだが、その後の置換作業で一工夫し てある。 半角全角変換の際は完全に連想配列に依存していたが、ひらがな・カタカナ変換においては、高速にするた めに使用を控えている。その代わりにキャラクターコードを数百番ずっシフトするような計算を行っている。 UTF -8 においては、ひらがなとカタカナはユニコード番号が数十バイト離れたところにそれぞれマッピングさ れている * 19 ので、それを見ながらユニコード番号を数百番ずらして目的の文字を作っているというわけだ。 https : //uec. usp—lab. com/TUKUBAl/CGl/TUKUBAI. CGI?POMPA=ABOUT https://github.com/She11Shoccar—jpn/misc-t001s/b10b/master/kata2hira にアクセスし、そこにあるソースコードをコ ピー & ペーストしてもよいし、あるいは "RAW ”と書かれているリンク先を「名前を付けて保存」してもよい。 * 19 『オレンジェ房』さんの UTF -8 の文字コード表全角ひらがな・カタカナというべージ参照 → http : //orange-factory ・ com/samp1e/utf8/code3-e3.れtml * 17 * 18

8. Shell Script ライトクックブック

67 第 4 章 POS Ⅸ原理主義テクニック -Web 編 できることに驚いてくれる人が多いが、驚くのはまだ早い ! Web アプリケーションを作るうえで役立つ数々の 前章の POSIX 原理主義テクニックは堪能してもらえただろうか。筆者の周囲では JSON 、 XML のパースが 回答 問題 レシピ 4 ユ U RL デコードする のキーワードで Web 検索して動作画面やソースコードを見てみるといい。 アプリケーション「メトロバイバー」は、 し、本章のレシピを読めば現実味が湧く事だろっ レシピはこれから紹介するのだから。 これらのレシピを活用して作ったものだ。信じられないなら、これら 事実、ショッピングカートの「シェルショッカー」、東京メトロのオープンデータに基づく列車接近情報表示 そもそも POSIX の範囲で Web アプリケーションを作ること自体、驚く以前に、信じられないようだ。しか ワードは URL 工ンコードされた状態であり、デコードしないとわからないのでデコードしたい。 Web サーバーのログを見ていると、検索ページからジャンプしてきている形跡があった。しかし、検索キー こんな感じだ。 つかるたびに printf 関数を使ってその 16 進数に対応するキャラクターに置き換えればよい。 AWK で書くなら そんなに難しい仕事でないから素直に書いて作る。基本的には正規表現で "%C0-9A-Fa-f]{2} ”を検索し、見

9. Shell Script ライトクックブック

回答 は後回しにするが、そうやって制作した CSV パーサー いる。 54 レシピ 3.5 CSV ファイルを読み込む 問題 sed や AWK を駆使すれば POSIX の範囲でパーサー ( 解析プログラム ) の作成が可能である。原理の解説 第 3 章 POSIX 原理主義テクニック Excel から工クスポートした CSV ファイルの任意の行の任意の列を読み出したい。しかし実際読み出すと なったら、列区切りとしてカンマと値としてのカンマを区別しなければいけなかったり、行区切りとしての改 行と値としての改行を区別しなければいけなかったり、さらに値としてのカンマや改行を区別するためのダブ ルクオーテーション記号を意識しなければいけなかったり、大変だ。 parsrc. sh ”があるので、それをダウンロード * 3 して用 例えば、次のような CSV ファイル (sample. csv) があったとする。 cc " , d d これを次のようにして parsrc. sh に掛けると、第 1 列 : 元の値のあった行番号、第 2 列 : 元の値のあった列番号、 第 3 列 : 値、という 3 つの列から構成されるテキストデータに変換される。 ・ /parsrc. sh sample. csv ロ 1 1 1 1 2 1 2 b"bb 1 f , f 4 d d 3 c*ncc ←値としての改行は "*n ”に変換される ( オプションで変更可能 ) よって、後ろにパイプ越しにコマンドを繋げば「任意の行の任意の列の値を取得」もできるし、 ついて指定した列の値を抽出」などということもできる。 * 3 https://github. com/SheIIShoccar-jpn/Parsrs/b10b/master/parsrc.sh にアクセスし、そこにあるソースコードをコピー & ペーストしてもよいし、あるいは "RAW ”と書かれているリンク先を「名前を付けて保存」してもよい。 「全ての行に

10. Shell Script ライトクックブック

96 第 4 章 POSIX 原理主義テクニックー Web 編 と、書き換えればよい。たったの 4 行になる。 sessionf のサプコマンド "avail ”は、有効なものがあれば延命、 無ければ新規作成を意味する。そして後ろの "at ”プロバティーは、セッションファイルの場所と、無かった 場合のセッションファイルのテンプレートを mktemp と同じ書式で指定するものであり、 "lifetime ”プロバ ティーは、有効期限を判定するための秒数を指定するものだ。 一方、セキュリティーを高めるため、有効なセッションがあった場合には既存のセッションファイルの名前と 共にセッション ID を付け替えたい、ということであればサプコマンドを "renew ”にするだでよい。 Fi1e—session=$ (sessionf renew " $session-id" at=$Dir—SESSION/XXXXXXXXXXXXXXXXXXXXXXXX" \ session—id=${Fi1e—session##*/} esac * ) session_status='new' case $ ? in 0 ) sesslon_status='exist ・・ 1ifemin=$SESSION_LIFETIME →レシピ 5.22 (mktemp コマンド ) →レシピ 4.10 ( シェルスクリプトおばさんの手づくり Co 。 kie ( 書き込み編 ) ) →レシピ 4.9 ( シェルスクリプトおばさんの手づくり C 。。 kie ( 読み込み編 ) ) →レシピ 3.3 ( シェルスクリプトで時間計算を一人前にこなす ) 参照 CentOS 6 以降ではこの問題は解消されている。 いということだ。だから文字列を長くしてランダム文字列の不規則性を高めてやらなければならない。ちなみに たプロセス ID なのだ。つまり、 CentOS 5 の mktemp コマンド実装は、ランダム文字列としての質が低 生成されたランダムなはずのファイル名の末尾を見ると数字になっている。なんとこれはその時に発行され /tmp/sPr10701 $ mkt emp /tmp/XXXXXXXX ロ / tmp / 0YA10700 $ mktemp /tmp/XXXXXXXX ロ •CentOS 5 で mktemp コマンドを実行すると・・ 動かせる環境があれば実際に試してみるとよくわかる。 ”という記述の "x ”は長めにするべきである。理由は、 CentOS 5 を 文字列の長さを指定するための "xxxx.. これは、 sessionf コマンドというより、依存している mktemp コマンドに起因する問題であるが、ランダムな "XXXX . ”は長めにするべき sessionf の詳しい使い方については、ソースコードの冒頭にあるコメントを参照されたい。