Linuxゲリラ戦記

私の気持ち > 憧れの女性
ERROR:permission denied:許可がありません

44.Google画像検索API。返ってきた結果を整理する。catコマンド。trコマンド。リダイレクト

ナックス「はい。今回はGoogle画像検索APIの『結果の見方』の解説です」

デビー君「はーい」

ナックス「とりあえず今回は検索キーワードをdogにして、以下のような感じでクエリを作成してみます」

http://ajax.googleapis.com/ajax/services/search/images?q=dog&v=1.0

ナックス「検索キーワードをURLエンコードするのが面倒くさかったので、今回は犬と言う意味の英語にしてみました。英語は基本的にURLエンコードする必要がありません。いいなぁー」

ナックス「こいつを例のごとくcurlコマンドを使ったあんな感じにして実行します」

$ curl -e http://www.my-ajax-site.com 'http://ajax.googleapis.com/ajax/services/search/images?q=dog&v=1.0'

結果が整理されていない

ナックス「うわ。だめだ……。整理されていないから解説しづらい……。とりあえず、テキストファイルとして > をつかって保存をしましょう」

$ curl -e http://www.my-ajax-site.com \
'http://ajax.googleapis.com/ajax/services/search/images?q=dog&v=1.0' > result.txt
$ curl -e http://www.my-ajax-site.com \
> 'http://ajax.googleapis.com/ajax/services/search/images?q=dog&v=1.0' > result.txt
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  3200    0  3200    0     0  31387      0 --:--:-- --:--:-- --:--:-- 2134k

リダイレクトする

デビー君「 > って何だっけ?」

ナックス「はい。 > は『リダイレクト』と言います。 < なんていうのもあります。33.ハッキングあたーっく!lwp-requestで情報を要求!/dev/nullはブラックホールでも少し出てきましたね。 > は、何かのコマンドを実行して出てきた結果を、ばしっと何かのファイルに書き込んでしまうやつです。今回は、なんとなーく result.txt という名前にしましたが。もちろん、どんな名前のファイルを指定しても構いません。また、ファイルは事前に作っておく必要もありません」

デビー君「おぉ。その説明を聞くと、33.ハッキングあたーっく!lwp-requestで情報を要求!/dev/nullはブラックホールで説明していた /dev/null の意味がちょっと分かる……」

ナックス「そうですね。コマンドを単純にそのまま理解すると、『出力結果を /dev/null というファイルに書き込んだぜ!』って言う意味ですが、 /dev/null は、書き込まれた物を自動的に消してしまいます。なんというか……出力結果のゴミ箱とでも言いましょうか……」

ナックス「なので、出力結果を特にテキストファイルに残しておく必用もなく、さらに『出力結果がいちいち出てくるのが邪魔だなー』って言うときに、33.ハッキングあたーっく!lwp-requestで情報を要求!/dev/nullはブラックホールで説明した様に > /dev/null みたいな使い方をするのです」

デビー君「なるほどねぇ」

ナックス「さて、きちんとresult.txtに結果を保存できているか cat コマンドで確認してみましょう」

デビー君「お!新しいコマンド。catコマンドはどういうときに使うの?」

ナックス「ファイルをチラ見するコマンドです」

デビー君「チラ見?」

ナックス「使い方はこんな感じ」

$ cat ファイル名

ナックス「早速result.txtにcatコマンドを使ってみましょう」

$ cat result.txt
$ cat result.txt
{"responseData": {"results":[{"GsearchResultClass":"GimageSearch","width":"450","height":"651","imageId":"2Fd-Y5-ClsyueM:","tbWidth":"95","tbHeight":"138","unescapedUrl":"http://www.hoax-slayer.com/images/worlds-strongest-dog.jpg","url":"http://www.hoax-slayer.com/images/worlds-strongest-dog.jpg","visibleUrl":"www.hoax-slayer.com","title":"Strongest \u003cb\u003eDog\u003c/b\u003e In The World Photograph","titleNoFormatting":"Strongest Dog In The World Photograph","originalContextUrl":"http://www.hoax-slayer.com/strongest-dog.shtml","content":"Real \u003cb\u003edog\u003c/b\u003e - Description","contentNoFormatting":"Real dog - Description","tbUrl":"http://images.google.com/images?q\u003dtbn:2Fd-Y5-ClsyueM::www.hoax-slayer.com/images/worlds-strongest-dog.jpg"},{"GsearchResultClass":"GimageSearch","width":"600","height":"530","imageId":"ENH8mUtG9B1SEM:","tbWidth":"135","tbHeight":"119","unescapedUrl":"http://www.harlemfur.com/images/Dog_Olive.jpg","url":"http://www.harlemfur.com/images/Dog_Olive.jpg","visibleUrl":"www.harlemfur.com","title":"\u003cb\u003eDogs\u003c/b\u003e Archives","titleNoFormatting":"Dogs Archives","originalContextUrl":"http://www.harlemfur.com/dogs/","content":"This note below is from a \u003cb\u003edog\u003c/b\u003e","contentNoFormatting":"This note below is from a dog","tbUrl":"http://images.google.com/images?q\u003dtbn:ENH8mUtG9B1SEM::www.harlemfur.com/images/Dog_Olive.jpg"},{"GsearchResultClass":"GimageSearch","width":"400","height":"366","imageId":"Z9TvdKv9YWdDOM:","tbWidth":"124","tbHeight":"113","unescapedUrl":"http://www.petwise.co.za/content/dog-best-friend-1.jpg","url":"http://www.petwise.co.za/content/dog-best-friend-1.jpg","visibleUrl":"www.petwise.co.za","title":"petwise.","titleNoFormatting":"petwise.","originalContextUrl":"http://www.petwise.co.za/live/content.php?Item_ID\u003d1311","content":"Are \u003cb\u003edogs\u003c/b\u003e humankind\u0026#39;s best","contentNoFormatting":"Are dogs humankind\u0026#39;s best","tbUrl":"http://images.google.com/images?q\u003dtbn:Z9TvdKv9YWdDOM::www.petwise.co.za/content/dog-best-friend-1.jpg"},{"GsearchResultClass":"GimageSearch","width":"390","height":"358","imageId":"Qzr608AiE4BrSM:","tbWidth":"123","tbHeight":"113","unescapedUrl":"http://www.gan.ca/images/hooks/dog.bmp","url":"http://www.gan.ca/images/hooks/dog.bmp","visibleUrl":"www.gan.ca","title":"Global Action Network: Animals: \u003cb\u003eDogs\u003c/b\u003e","titleNoFormatting":"Global Action Network: Animals: Dogs","originalContextUrl":"http://www.gan.ca/animals/dogs.en.html","content":"A \u003cb\u003edog\u003c/b\u003e","contentNoFormatting":"A dog","tbUrl":"http://images.google.com/images?q\u003dtbn:Qzr608AiE4BrSM::www.gan.ca/images/hooks/dog.bmp"}],"cursor":{"pages":[{"start":"0","label":1},{"start":"4","label":2},{"start":"8","label":3},{"start":"12","label":4},{"start":"16","label":5},{"start":"20","label":6},{"start":"24","label":7},{"start":"28","label":8}],"estimatedResultCount":"166000000","currentPageIndex":0,"moreResultsUrl":"http://www.google.com/images?oe\u003dutf8\u0026ie\u003dutf8\u0026source\u003duds\u0026start\u003d0\u0026hl\u003den\u0026q\u003ddog"}}, "responseDetails": null, "responseStatus": 200}

catコマンドでresult.txtの中身を見る

デビー君「なるほど。ファイルの中身を表示するわけね」

ナックス「そうです。さて、きちんと保存出来ているようなので、こいつを整理しましょう」

デビー君「nanoでファイルを開いて手作業で整理する?」

ナックス「その方が綺麗に整理できると思いますが、今回は『解説用にざっくりと見た目分かりやすくなれば良いかなー』な感じなので、単純に『,を改行に置き換える』というコマンドを打ちましょう」

デビー君「『改行』ってなに?」

ナックス「行を変える……簡単に言えば、次の行にいく。えーっと、普通、文章を書くときにEnterキーで次の行にいくでしょ?それをコマンドで実行しよう、ってことです。今は、全部が一行に収まってるから、もうちょっと見た目を見やすくしたいよね」

デビー君「ふむふむ」

ナックス「さて『改行』と聞くと、難しく聞こえますが、実は改行は『\n』という文字で表せます」

デビー君「ん?『\n』が『改行』って言う意味、ってこと?」

ナックス「そうです。つまり、全ての『,』を『\n』という文字に置き換えれば綺麗に改行されることになります」

ナックス「ちなみに、文字を置き換えることを、プログラマーの間では『置換(チカン)する』と言います」

デビー君「『チカンする』……なるほど、変態ですね」

ナックス「そうです。変態なんです」

ナックス「さて、置換をするコマンド。デビー君は過去にやったのを覚えていますか?」

デビー君「え?うーん……そんなイヤらしいコマンドは習った記憶が無いけど……」

ナックス「そうですね。確かにあまりにもサラッと出てきたので、忘れてしまっていても無理はありません。えーっと40.Linuxのコマンドから行うURLエンコード、URLデコードをちょっとチェックしてみてください」

デビー君「どれどれ?……あ!もしかしてtrコマンド?」

$ tr 変換したい文字 変換後の文字

ナックス「そうです!trコマンドは実はイヤらしいコマンドだったのです!」

デビー君「そうだったのか!」

ナックス「ただ、trコマンドは置換コマンドとして非力な方で、変換する文字の指定『変換したい文字』『変換後の文字』の文字列の長さを同じにしないといけないようです」

ナックス「ということで本来なら別のコマンドを使って『,』→『\n』ではなく『,』→『,\n』とする方法を教えるのが解説サイトとしても正しいやり方──だと思いますが、まあ、今日はせっかくcatコマンドとリダイレクトを教えたので、そいつを活用する、と言う意味でtrコマンドを使った『,』→『\n』の変換を行います。別の置換コマンドはまた今度解説致します」

デビー君「はーい」

ナックス「catコマンドと組み合わせて、こんな感じでどうよ!?」

cat result.txt | tr , \\n > seiri.txt

trコマンドを使って置換し、それをseiri.txtに書き込む

デビー君「おー。何か、パイプとかリダイレクトとか使いまくっていて、『Linux使ってるなー』って感じだね」

デビー君「……あれ?これ、間違ってるよ。\nじゃなくて、\\nになっちゃってるよ?」

ナックス「いいえ。こいつでいいんです。むしろ、こいつでなくちゃ駄目なんです」

ナックス「30.シェルスクリプトでプログラミングする前の予習。echoコマンド。exprコマンド。\によるエスケープ処理をちらっとチェックしてみてください」

デビー君「えーっと……。あ。『掛け算の * はそのまま使うと正規表現のアスタリスクになっちゃうから\でエスケープ処理をしよう』って書いてある」

ナックス「そうです。エスケープ処理です」

デビー君「なるほど。『\n』も『改行』という意味の特殊な文字だから、事前に\をつけてエスケープ処理をするんだね!?」

ナックス「いいえ。ハズレです」

デビー君「えっ!?」

ナックス「確かに『\n』は一瞬、特殊な意味をもつ何か……つまり、アスタリスクのような種類の様に感じられるかもしれませんが、実は『\n』は純粋に『あ』とか『a』とかと同じく、普通の文字という認識で構いません」

デビー君「じゃあ、なんで『\n』の前に『\』が必要なのさ?」

ナックス「正確には『\n』の前に『\』が必要なのではなく『\』の前に『\』が必要なのです」

デビー君「??????」

デビー君「──!!分かった!『\』は『エスケープ処理』という意味の特殊な文字だ!!」

ナックス「そうです。『\』は普通に使うと『エスケープ処理』という特殊な意味を持ってしまうのでその前に『\』を使ってエスケープ処理をすることで『\はエスケープ処理という意味ではありません』という意味になるのです」

デビー君「ややこしっ!!」

ナックス「はい。謎が解明できた所でcatコマンドでseiri.txtを見てみましょう」

$ cat seiri.txt
$ cat seiri.txt 
{"responseData": {"results":[{"GsearchResultClass":"GimageSearch"
"width":"450"
"height":"651"
"imageId":"2Fd-Y5-ClsyueM:"
"tbWidth":"95"
"tbHeight":"138"
"unescapedUrl":"http://www.hoax-slayer.com/images/worlds-strongest-dog.jpg"
"url":"http://www.hoax-slayer.com/images/worlds-strongest-dog.jpg"
"visibleUrl":"www.hoax-slayer.com"
"title":"Strongest \u003cb\u003eDog\u003c/b\u003e In The World Photograph"
"titleNoFormatting":"Strongest Dog In The World Photograph"
"originalContextUrl":"http://www.hoax-slayer.com/strongest-dog.shtml"
"content":"Real \u003cb\u003edog\u003c/b\u003e - Description"
"contentNoFormatting":"Real dog - Description"
"tbUrl":"http://images.google.com/images?q\u003dtbn:2Fd-Y5-ClsyueM::www.hoax-slayer.com/images/worlds-strongest-dog.jpg"}
{"GsearchResultClass":"GimageSearch"
"width":"600"
"height":"530"
"imageId":"ENH8mUtG9B1SEM:"
"tbWidth":"135"
"tbHeight":"119"
"unescapedUrl":"http://www.harlemfur.com/images/Dog_Olive.jpg"
"url":"http://www.harlemfur.com/images/Dog_Olive.jpg"
"visibleUrl":"www.harlemfur.com"
"title":"\u003cb\u003eDogs\u003c/b\u003e Archives"
"titleNoFormatting":"Dogs Archives"
"originalContextUrl":"http://www.harlemfur.com/dogs/"
"content":"This note below is from a \u003cb\u003edog\u003c/b\u003e"
"contentNoFormatting":"This note below is from a dog"
"tbUrl":"http://images.google.com/images?q\u003dtbn:ENH8mUtG9B1SEM::www.harlemfur.com/images/Dog_Olive.jpg"}
{"GsearchResultClass":"GimageSearch"
"width":"400"
"height":"366"
"imageId":"Z9TvdKv9YWdDOM:"
"tbWidth":"124"
"tbHeight":"113"
"unescapedUrl":"http://www.petwise.co.za/content/dog-best-friend-1.jpg"
"url":"http://www.petwise.co.za/content/dog-best-friend-1.jpg"
"visibleUrl":"www.petwise.co.za"
"title":"petwise."
"titleNoFormatting":"petwise."
"originalContextUrl":"http://www.petwise.co.za/live/content.php?Item_ID\u003d1311"
"content":"Are \u003cb\u003edogs\u003c/b\u003e humankind\u0026#39;s best"
"contentNoFormatting":"Are dogs humankind\u0026#39;s best"
"tbUrl":"http://images.google.com/images?q\u003dtbn:Z9TvdKv9YWdDOM::www.petwise.co.za/content/dog-best-friend-1.jpg"}
{"GsearchResultClass":"GimageSearch"
"width":"390"
"height":"358"
"imageId":"Qzr608AiE4BrSM:"
"tbWidth":"123"
"tbHeight":"113"
"unescapedUrl":"http://www.gan.ca/images/hooks/dog.bmp"
"url":"http://www.gan.ca/images/hooks/dog.bmp"
"visibleUrl":"www.gan.ca"
"title":"Global Action Network: Animals: \u003cb\u003eDogs\u003c/b\u003e"
"titleNoFormatting":"Global Action Network: Animals: Dogs"
"originalContextUrl":"http://www.gan.ca/animals/dogs.en.html"
"content":"A \u003cb\u003edog\u003c/b\u003e"
"contentNoFormatting":"A dog"
"tbUrl":"http://images.google.com/images?q\u003dtbn:Qzr608AiE4BrSM::www.gan.ca/images/hooks/dog.bmp"}]
"cursor":{"pages":[{"start":"0"
"label":1}
{"start":"4"
"label":2}
{"start":"8"
"label":3}
{"start":"12"
"label":4}
{"start":"16"
"label":5}
{"start":"20"
"label":6}
{"start":"24"
"label":7}
{"start":"28"
"label":8}]
"estimatedResultCount":"166000000"
"currentPageIndex":0
"moreResultsUrl":"http://www.google.com/images?oe\u003dutf8\u0026ie\u003dutf8\u0026source\u003duds\u0026start\u003d0\u0026hl\u003den\u0026q\u003ddog"}}
 "responseDetails": null
 "responseStatus": 200}

seiri.txtの中身を見る

デビー君「おー。整理できてる」

ナックス「ざっくりとですけど、まあ以前よりは読みやすいでしょう」

デビー君「でもナックス。一つ質問なんだけど……」

ナックス「はいはい」

デビー君「最後に > seiri.txt じゃなくて、 > result.txt にしたら、無駄にファイルを作成すること無くてスマートじゃない?」

ナックス「そうなんですよね。そいつが出来ればスマートなんですが……」

デビー君「え?出来ないの?」

ナックス「Linux初心者がよく陥る罠なのですが、リダイレクトを使用したときに、リダイレクト元のファイルと、リダイレクト先のファイルを同じファイルで指定すると、そのファイルの中身が空になります」

デビー君「空?」

ナックス「つまり、中の文字が全て消えてしまった、何も書かれていないファイルです」

デビー君「なんでそうなるの?」

ナックス「私も所詮アマチュアLinuxユーザーなので、詳しくは知らないのですが、Linuxはまず、C言語で作られています」

デビー君「ふむふむ」

ナックス「で、ファイルを指定すると、C言語内部ではポインタというのを使ってデータを指定するそうな」

デビー君「ほうほう」

ナックス「『で、ポインタで同じデータを指定するのって良くないよね』みたいな話じゃそうな」

デビー君「え?……つまり、どういうこと?」

ナックス「めでたしめでたし」

デビー君「いやいや、ナックス。誤魔化さないで」

ナックス「まぁ、試しにやってみてください。特にエラーが起こるとかじゃなくて、本当に単純にファイルが空になるだけです。ファイル自体も、特殊なファイルになってしまうとかじゃなくて、普通のファイルのままです。中の文字が全部消える、という、ただそれだけ」

ナックス「さて、意外と時間がかかったので、結果の見方は次回(45.Google画像検索API。返ってきた結果を解読しよう。)!!」

補足

リダイレクトの説明で嘘をつきました

ごめんなさい。リダイレクトの説明で嘘をつきました。正確にはリダイレクトは『バシッとファイルに書き込む』ための物ではなく、『出力結果が出る先を変える』ものです。何もしなければ出力結果は『画面』に出ますが、リダイレクトを使うことによって出力結果を『ファイル』に変えているのです。

今回のcatコマンドを使用すると、結果の終わりの中途半端な所に次のコマンドを打つための $ が出てしまいます。

はい。Linuxでは良くあります。そこから次のコマンドを打っても何の問題もありません。このままコマンドを打つのは気持ち悪い、と思う人は、何のコマンドも入力せずにEnterキーを押してください。次の行にいけます。

説明は一応理解できましたが、$ tr , \\n の結果は ,→\nではなく ,→nな気もします、

そうですね。私も気持ちは分かります。「trは同じ文字数同士しか置換できない。,は一文字。\nは二文字。じゃあ、うまく置換できないんじゃない?」という話ですよね。すいません。改行は、特別扱いで「\n」で一文字なんです……。納得できない方はごめんなさい。

空(そら)ですか?

いいえ。『からっぽ』の『から(空)』です。からっぽは、漢字で書くと空っぽになるのです。なんだかロマンチックですね。

解説での返ってきたデータと、私が実際にコマンドを試して返ってきたデータが微妙に違うのですが……

はい。なんせGoogle画像検索の情報です。情報は日夜アップデートされているので、結果が違うのは当然です。でも、今後の解説には何の問題もございませんので安心してください。

Google API使用できなくなってるんだけど?

はい。Google API使用できなくなってるど思うので、代わりのアドレスを用意しました。解説では、

$ curl -e http://www.my-ajax-site.com 'http://ajax.googleapis.com/ajax/services/search/images?q=dog&v=1.0'

のようにしていますが、代わりに以下のようにコマンドを打ってください。

$ curl -e http://www.my-ajax-site.com 'http://www.garunimo.com/program/linux/search/images.php?q=dog&v=1.0'

ちなみに、代わりのアドレスの方は実際の検索機能はないので、例えばq=dogの代わりにq=bigdogとか指定しても、結果は変わらないよ。このアドレスはあくまで解説用だよ。

このエントリーをはてなブックマークに追加