本記事は『コマンドラインの黒い画面が怖いんです。 新人エンジニアのためのコマンドが使いこなせる本』(kanata著)の「第5章 たった1行でできる作業効率化!」から一部を抜粋したものです。掲載にあたって編集しています。
本記事また本書は動作環境としてWindowsを想定しています。
インターネットから必要な情報を得よう
読者の皆さんはインターネットへのアクセスはもっぱらブラウザ経由で行っているかと思いますが、CLIでもアクセスすることができます。必要な情報をインターネットから取得して、作業を効率化できます。
天気を知る
手始めに、天気予報を表示してみます。ターミナルから天気を確認できるサービスがあります。
ブラウザの代わりにインターネットにアクセスして情報を取得できるコマンドとしてcurlを使用します。書式は次の通りです。
curl -s [ 任意のURL]
-sオプションは、処理の進捗状況を表示しないようにするオプションです。処理自体には影響しませんので指定しなくてもかまいません。
次の通り入力してターミナルから天気を確認できるサービス(https://wttr.in)にアクセスしてみましょう。
$ curl -s https://wttr.in
紙幅の都合上、実行結果は掲載しませんが、コマンドを実行すると天気予報の情報が一覧で表示されます。
「curl -s https://wttr.in」だけで現在地の天気が確認できますが、例えば「curl -s https://wttr.in/ 沖縄」や「curl -s https://wttr.in/Hirosaki」と指定すると任意の地域を確認できます。ぜひ試してみてください。もちろん、このサービスは同じ内容をWebブラウザからでも確認できます。
郵便番号から住所を得る
次に、郵便番号から対応する住所を表示する方法をご紹介します。
次のように記述することで、郵便局のWebサイトに問い合わせて、結果から必要な情報を抽出します。「ZIP=」に続く数字の部分が郵便番号で すので、調べたい郵便番号を入力してみてください(アクセス先に配慮し、短時間に連続して実行することは控えましょう。)。
$ ZIP=1050011;curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP | grep -e '<td class="data"><small>' -e '<p><small><a class="line"' |sed 's/<[^>]*>//g' | tr -d \\t | xargs 東京都 港区 芝公園
このワンライナーは、次の処理を順に行っています。
(1)ZIP:変数ZIPを用意し、郵便番号を設定する
シェルは、他のプログラミング言語と同様に変数を使用できます。設定は次のように記述します。
[任意の変数名]=[任意の値]
郵便番号から住所を取得した先の例では、変数名ZIPに1050011という値を設定しています。この値はシェルが終了するまで(ターミナルを終了するまで)消えることなく何度も参照できます。変数名の先頭に$を設定することで参照できます。以下は、変数ZIPに対する設定および参照を実行した例です。
変数ZIPに設定された郵便番号は、次のcurlの処理で使用します。
$ ZIP=1050011 # 変数ZIP に値を設定 $ echo $ZIP # 変数ZIP に設定された値を表示 1050011
(2)curl:郵便局のWebサイトから住所の情報を取得する
郵便局のWebサイトから郵便番号をもとに住所を表示するには次のURLにアクセスします
https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=[任意の郵便番号]
結果はブラウザでも確認できますが、curlでも確認できます。
$ ZIP=1050011 $ curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8"> <meta http-equiv="Content-Style-Type" content="text/css"> <meta http-equiv="Content-Script-Type" content="text/javascript"> <title>郵便番号 1050011 の検索結果 - 日本郵便</title> ・ ・ ・ (省略)
大量の結果が出力されました。ブラウザでアクセスするとグラフィカルに表示されますが、curlでアクセスするとそのグラフィカルな表示の元となるHTMLなどが表示されるようになります。ここから必要な情報だけを抜き出したいため、結果をパイプでgrepに渡します。
(3)grep:住所が記録されている行を抽出する
curlで得た大量の結果を調べると、住所が書かれた箇所を見つけることができました。
<tr> <td class="data"> 〒<small>105-0011</small></td> <td class="data"><small> 東京都</small></td> <td class="data"><small> 港区</small></td> <td> <div class="data"> <p><small><a class="line" href="zipcode.php?pref=13&city=1131030&id=47421&merge="> 芝公園</a></small></p> <span class="comment_zipsearch"> <small>シバコウエン</small></span> </div> </td>
住所が書かれている行だけをgrepで抽出します。次の2パターンで抽出できそうです。
- <td class="data"><small>が含まれている行
- <p><small><a class="line"が含まれている行
grepを使って試してみます。「どちらかが含まれている行を抽出する」には-eオプションを使用します。
$ ZIP=1050011;curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP | grep -e '<td class="data"><small>' -e '<p><small><a class="line"' <td class="data"><small>東京都</small></td> <td class="data"><small>港区</small></td> <p><small><a class="line" href="zipcode.php?pref=13&city=1131030&id=47421&merge=">芝公園</a></small></p> (紙面の都合により結果に含まれる多量の空白を削除しています)
住所が含まれた行だけを抽出することができました。これを編集すれば住所だけが得られそうです。この結果を次のsedに渡します。
(4)sed:HTMLのタグ(<と>で囲まれた文字列の部分)を削除する
sedを利用して、HTML のタグを削除するイディオムがあります。書式は以下の通りです。
sed 's/<[^>]*>//g'
正規表現を利用して<と>で囲まれた箇所を削除する処理となっています。正規表現は、あらゆる文字列を1つの形式で表現するための非常に強力な表現方法です。
正規表現の解説は本書では詳細を割愛しますが、陳腐化せず、長く活用できる技術になりますので、気になる方はインターネット等で詳細を確認 してみてください。
sedで編集した結果は次の通りになります。
$ ZIP=1050011;curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP | grep -e '<td class="data"><small>' -e '<p><small><a class="line"' |sed 's/<[^>]*>//g' 東京都 港区 芝公園
不要な空白(タブ)や改行が入っていますが住所だけが取得できました。もう一息です。この結果をtrに渡して、不要な空白(タブ)を削除します。
(5)tr:タブを削除する
trは以前の章で解説した通り、任意の文字を削除できます。タブはシェル上では\\tと表現できるので、タブの削除は次の書式になります。
tr -d \\t
結果を確認してみます。
$ ZIP=1050011;curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP | grep -e '<td class="data"><small>' -e '<p><small><a class="line"' |sed 's/<[^>]*>//g' 東京都 港区 芝公園
不要な空白が削除できました。これで目的達成でもいいのですが、最後に住所を横並びにして締め括りとしましょう。結果を次のxargsに渡します。
(6)xargs:結果を横一列に並べる
パイプ経由でxargsに結果を渡すことで横一列に並べてくれます。xargsは本来、パイプから受け取った値をそのまま任意のコマンドの引数とするコマンドですが、横に並べるテキスト編集に使えるというちょっとしたテクニックがあります。最終的に、郵便番号から住所が取得できました。
$ ZIP=1050011;curl -s https://www.post.japanpost.jp/cgi-zip/zipcode.php?zip=$ZIP | grep -e '<td class="data"><small>' -e '<p><small><a class="line"' |sed 's/<[^>]*>//g' 東京都 港区 芝公園
フォルダをZIPファイルにバックアップする
Windowsでは右クリックからコンテキストメニューを表示することで「ZIPファイルに圧縮する」という機能を使うことができます。
これをCLIでやってみましょう。zipコマンドを使えば簡単に実行できます。書式は次の通りです。-rオプションは圧縮対象のディレクトリの中のサブディレクトリもすべて対象にして圧縮するオプションです。
zip -r [ 作成されるZIP ファイル名] [ 圧縮対象のディレクトリ]
次に示すのは、textdataディレクトリを中身も含めてすべて圧縮し、backup.zipを作成する例です。圧縮結果が表示されています。textdata ディレクトリに格納されているテキストファイルは元のサイズの半分程度に圧縮されました。
$ zip -r backup.zip textdata adding: textdata/ (stored 0%) adding: textdata/bocchan.txt (deflated 55%) adding: textdata/hashire_merosu.txt (deflated 50%)
意図通りZIPファイルが作成されているか確認してみます。元のディレクトリtextdataとZIPにしたbackup.zipがあることが確認できます。
$ ls -l 合計 104 -rwxrwxrwx 1 user user 105463 5 月 14 08:48 backup.zip drwxrwxrwx 1 user user 4096 5 月 14 08:46 textdata
ZIPファイルに何が格納されているかは、unzipコマンドの-lオプションを利用するとZIPファイルを展開せずに確認できます。
$ unzip -l backup.zip Archive: backup.zip Length Date Time Name --------- ---------- ----- ---- 0 2023-10-06 07:20 textdata/ 209990 2023-10-06 07:20 textdata/bocchan.txt 21563 2023-10-06 07:19 textdata/hashire_merosu.txt --------- ------- 231553 3 files
unzipにオプションを指定しなければ、カレントディレクトリにzipファイルが展開されます。
$ unzip backup.zip Archive: backup.zip creating: textdata/ inflating: textdata/bocchan.txt inflating: textdata/hashire_merosu.txt
処理した結果をクリップボードにコピーする
これまで本書で解説した方法は、コマンドの実行結果を画面に表示したり、ファイルに出力したりするものが中心でした。実は、この実行結果の出力先はクリップボードにすることもできます。クリップボードに出力すれば、実行結果をExcelやメモ帳に容易に貼り付けることができます。
書式はコマンドの最後に「 | clip.exe」と記載するだけです。次に示すのはdateで得られる結果をクリップボードにコピーする例です。貼り付け先のソフトウェアの仕様に合わせて、文字コードをCP932に変換する処理を入れています。メモ帳やExcelに貼り付ける際にはCP932への変換が必要です。
$ date +%Ec | nkf -s --cp932 | clip.exe