Y's note

Web技術・プロダクトマネジメント・そして経営について

本ブログの更新を停止しており、今後は下記Noteに記載していきます。
https://note.com/yutakikuchi/

標準入出力プログラミング

入門Unixオペレーティングシステム

入門Unixオペレーティングシステム

標準入力

今日は簡単なメモ書きです。標準入力の使い方について少しだけ話します。
プログラム中で容量があるデータを一度ファイルに落として、その落としたファイルに対して別のプログラムを呼び出すような処理がかかれているのを時たま目にします。見る度に良い方法ではないと感じます。例えば1processで1fileを生成するような場合は、processに比例してfile数とDisk圧迫が重なります。重要なシステムでログファイルを記録するなどの使い方ではない限りfileを中継する方法は辞めましょう。代わりに実行コマンドへの標準入力で対応する方が効率的です。
標準入力とはUnix/Linuxで広く用いられているプログラムへの入力方法で、Keybord入力のコマンドライン引数、プログラムから別のプログラムへ入力する方法などを意味します。BigData処理のHadoopStreamingも標準入出力を利用しています

標準出力

標準入力によるデータ受け取りを行うプログラムに対して標準出力により受け渡しを行います。標準出力はプログラム内部でprintされる結果であったり、単純なUnix/Linuxコマンドのechoだったり、ヒアドキュメントで作る事も可能です。標準入力に複雑なデータ構成を必要とする場合はプログラム言語で記述、それ以外はechoやヒアドキュメントで十分だと思います。Sampleを以下に記述します。

プログラム言語での出力

ただprintするだけです。2列のデータを作ります。列の表現をタブ(\t)で、行を改行(\n)で表現します。このファイルをoutput.plとします。

#!/usr/bin/perl
use strict;
use warnings;
print "title\tdetail\nこんにちは\tこんにちはYutaKikuchiさん\nこんばんは\tこんばんはYutaKikuchiさん";
title	detail
こんにちは	こんにちはYutaKikuchiさん
こんばんは	こんばんはYutaKikuchiさん
echoコマンドでの出力

echoは代表的なUnix/Linuxの出力コマンドです。-eオプションを利用してタブや改行によるデータを出力します。

$ man echo
オプション
       -n     行末の改行を行わない。
       -e     string   中の、バックスラッシュでエスケープされた文字の解釈を有効にする。それぞれの意味は以下の通り:
              \a     アラート (ベル)
              \b     バックスペース
              \c     行末の改行を出力しない
              \f     フォームフィード (form feed)
              \n     改行 (newline)
              \r     復帰 (carriage return)
              \t     水平タブ
              \v     垂直タブ
              \\     バックスラッシュ
              \0nnn  アスキーコードが nnn (8 進) の文字

$ echo -e "title\tdetail\nこんにちは\tこんにちはYutaKikuchiさん\nこんばんは\tこんばんはYutaKikuchiさん"
title	detail
こんにちは	こんにちはYutaKikuchiさん
こんばんは	こんばんはYutaKikuchiさん
ヒアドキュメント

リダイレクト(<<)を利用してコマンドラインスクリプトファイル中に入力データを記述する事ができます。簡単な標準入力を利用する時はヒアドキュメントが最も利用されるかもしれません。リダイレクトの後に_EOT_やEOTなどの文字列を入力し改行するとheredocを入力モードに切り替わります。ちなみにEOTはEnd Of Textの略です。入力が終わった時に再度_EOT_と実行すると結果が出力されます。

$ cat << _EOT_
heredoc> title  detail
heredoc> こんにちは     こんにちはYutaKikuchiさん
heredoc> こんばんは     こんばんはYutaKikuchiさん       
heredoc> _EOT_
title	detail
こんにちは 	こんにちはYutaKikuchiさん
こんばんは		こんばんはYutaKikuchiさん

入出力の実行

入力受け取りプログラム

上で定義した標準入出力を受け取るプログラムを以下のように定義します。1行目のデータ項目の削除とdetail部分のみを抽出するようなプログラムです。このファイルをinput.plとします。

#!/usr/bin/perl
use strict;
use warnings;

my $i=0;
while( <STDIN> ) {
  chomp $_;
  $i++;
  my @data = split( /\t/, $_ );
  if( $i == 1 ) {
    print "\n";
    next;
  }
  print $data[1] . "\n";
}
プログラムとパイプを利用した入力

上で定義したoutput.plとinput.plをパイプ(|)でつなぎます。パイプは別のプログラムへの入力に渡すため命令です。

$ perl output.pl | perl input.pl 

こんにちはYutaKikuchiさん
こんばんはYutaKikuchiさん
echoとパイプを利用した入力

上のプログラムの例と同様でパイプでつなぎます。

$ echo -e "title\tdetail\nこんにちは\tこんにちはYutaKikuchiさん\nこんばんは\tこんばんはYutaKikuchiさん" | perl input.pl 

こんにちはYutaKikuchiさん
こんばんはYutaKikuchiさん
ヒアドキュメントでの入力

先ほどはcatとしていた部分をperl実行ブログラムに変更します。

$ perl input.pl << _EOT_
title   detail
こんにちは      こんにちはYutaKikuchiさん
こんばんは      こんばんはYutaKikuchiさん
_EOT_

こんにちはYutaKikuchiさん
こんばんはYutaKikuchiさん

まとめ

  • 標準入出力はHadoopのStreamingでも利用されています。
  • 標準入出力を利用すれば入力データを一時的なファイルに落としこまなくて済みます。
  • パイプとリダイレクトの使い方を覚えて標準入出力を使います。
  • 標準入力を利用するにはいくつか方法があります。
    • 出力をするプログラムと入力を受けるプログラムをパイプ(|)で連結します。
    • 出力側がechoコマンドで出力し、パイプ(|)で入力側に渡します。
    • ヒアドキュメントで出力し、リダイレクト(<<)で入力側に渡します。