ホーム » 2022 » 6月 » 27

日別アーカイブ: 2022年6月27日

2022年6月
 1234
567891011
12131415161718
19202122232425
2627282930  

検索・リンク

リダイレクト・パイプ

Linuxを使う上で、キーボードでコマンドを入力しているが、こういうコマンドの管理を行うプログラムshell と呼ぶ。shell には、色々なものがある(sh, csh, bash, zsh)が、広く使われている bash( born-again shell )について説明する。最初に、コマンドの入出力を組み合わせるために重要となるリダイレクトとパイプについて説明し、次にコマンドなどの処理単位となるジョブやプロセスの考え方について説明を行う。

標準入出力とリダイレクト

出力リダイレクト

C言語のプログラミングで、プログラムの実行結果をレポートに張り付ける時はどのように行っているだろうか?多くの人は、実行画面を PrintScreen でキャプチャした画像を張り付けているかもしれない。しかし、数十行にわたる結果であれば何度もキャプチャが必要となる。
そこで、今日の最初はリダイレクト機能について説明する。

“gcc ファイル.c” は、C言語のプログラムをコンパイルし、a.out という実行ファイルを生成する。”./a.out” にてプログラムを実行する。実行する命令に、“> ファイル名” と書くと、通常の出力画面(標準出力) をファイル名に記録してくれる。これを出力リダイレクトと呼ぶ。また、“>> ファイル名” と書くと、既存ファイルの後ろに追記してくれる。

guest00@nitfcei:~$ cat helloworld.c
#include <stdio.h>
int main() {
    printf( "Hello World\n" ) ;
    return 0 ;
}

guest00@nitfcei:~$ gcc helloworld.c
guest00@nitfcei:~$ ./a.out
Hello World

guest00@nitfcei:~$ ./a.out > helloworld.txt

guest00@nitfcei:~$ cat helloworld.txt
Hello World

guest00@nitfcei:~$ ./a.out >> helloworld.txt

guest00@nitfcei:~$ cat helloworld.txt 
Hello World
Hello World 

入力リダイレクト

次に、1行に名前と3教科の点数が書いてある複数行に渡るデータの各人の平均点を求めるプログラムを考える。

guest00@nitfcei:~$ cp /home0/Challenge/2.1-RedirectPipe.d/avg-each-low.c .
guest00@nitfcei:~$ cat avg-each-low.c
#include <stdio.h>
// ((input))           ((output))
// saitoh  43  54 82   saitoh 59.67
// tomoko  89 100 32   tomoko 73.67
// mitsuki 79  68 93   mitsuki 80.00
int main() {
   char name[ 100 ] ;
   int point[ 3 ] ;
   while( scanf( "%s%d%d%d" ,
                 name , &point[0] , &point[1] , &point[2] ) == 4 ) {
      double sum = 0.0 ;
      for( int i = 0 ; i < 3 ; i++ )
         sum += point[i] ;
      printf( "%s %6.2f\n" , name , sum / 3.0 ) ;
   }
   return 0 ;
}

guest00@nitfcei:~$ gcc avg-each-low.c
guest00@nitfcei:~$ ./a.out
saitoh 43  54 82    入力
saitoh 59.67        出力
tomoko 89 100 32    入力
tomoko 73.67        出力
^D             ← Ctrl-D を押すとファイル入力を終了

しかし、プログラムの書き方を間違えてプログラムを修正していると、動作確認のたびに何度も同じデータを入力するかもしれないが、面倒ではないだろうか?

プログラムを実行する時に、“< ファイル名” をつけると、通常はキーボードから入力する所を、ファイルからの入力に切り替えて実行することができる。このようなscanf()を使う時のようなプログラムの入力を標準入力といい、それをファイルに切り替えることを入力リダイレクトと呼ぶ。

guest00@nitfcei:~$ cp /home0/Challenge/2.1-RedirectPipe.d/name-point3.txt .

guest00@nitfcei:~$ cat name-point3.txt
saitoh  43  54 82
tomoko  89 100 32
mitsuki 79  68 93 

guest00@nitfcei:~$ ./a.out < name-point3.txt
saitoh  59.67
tomoko  73.67
mitsuki 80.00

この入力リダイレクトと出力リダイレクトを合わせて使うこともできる。

guest00@nitfcei:~$ ./a.out < name-point3.txt > name-avg.txt

guest00@nitfcei:~$ cat name-avg.txt
saitoh  59.67
tomoko  73.67
mitsuki 80.00

パイプ

先の名前と3教科のプログラムの結果から、全員の平均点をも計算したい場合、どのようなプログラムを作るだろうか?C言語だけの知識なら、各人の行のデータを計算するループの中に、全員の合計と人数を求めるプログラムを書いて、最後に平均点を出力するだろう。

一方で、複数人の名前と平均点のデータから平均点を求めるプログラムを書いて、前述のプログラムの実行結果を使う人もいるだろう。

以下の例では、“gcc -o avg-each-row avg-each-row.c” で、avg-each-row という実行ファイル、“gcc -o avg-all avg-all.c” で、avg-all という実行ファイルを生成し、avg-each-row で入力リダイレクト・出力リダイレクトを使って、name-avg.txt を作り、avg-all を入力リダイレクトで、最終結果を表示している。

guest00@nitfcei:~$ cp /home0/Challenge/2.1-RedirectPipe.d/avg-all.c .
guest00@nitfcei:~$ cat avg-all.c
#include <stdio.h>
// ((input))      ((output))
// saitoh  59.67  73.11
// tomoko  73.67
// mitsuki 80.00
int main() {
   char name[ 100 ] ;
   double point ;
   double sum = 0 ;
   int count = 0 ;
   while( scanf( "%s%lf" , name , &point ) == 2 ) {
      sum += point ;
      count++ ;
   }
   printf( "%6.2f\n" , sum / (double)count ) ;
   return 0 ;
}

guest00@nitfcei:~$ gcc -o avg-each-low avg-each-low.c
guest00@nitfcei:~$ gcc -o avg-all avg-all.c

guest00@nitfcei:~$ ./avg-each-low < name-point3.txt > name-avg.txt

guest00@nitfcei:~$ ./avg-all < name-avg.txt
71.11

しかし、いちいち入出力の結果を name-avg.txt を作るのは面倒である。であれば、以下の様なイメージで処理をすれば答えが求まる。

name-point3.txt(avg-each-row)name-avg.txt(avg-all)結果

これは、パイプ機能を使って以下の様に動かすことができる。

guest00@nitfcei:~$ ./avg-each-low < name-point3.txt | ./avg-all
71.11

guest00@nitfcei:~$ cat name-point3.txt | ./avg-each-low | ./avg-all
71.11

プログラムを実行する時に、“A | B” ように書くと、プログラムA の標準出力結果を、プログラムB の標準入力に接続させて、2つのプログラムを実行できる。このような機能を、パイプと呼ぶ。上記例の2つめ “cat… | ./avg-each-low | ./avg-all” では3つのプログラムをパイプでつないでいる。


リダイレクトのまとめ

 

入力リダイレクト(標準入力) 実行コマンド < 入力ファイル
出力リダイレクト(標準出力) 実行コマンド > 出力ファイル
 出力リダイレクト(標準出力の追記) 実行コマンド >> 出力ファイル
 標準エラー出力のリダイレクト 実行コマンド 2> 出力ファイル
パイプ
コマンドAの標準出力をコマンドBの標準入力に接続
コマンドA | コマンドB

C言語のコンパイルまとめ

 

C言語のコンパイル(実行ファイルはa.out) gcc ソースファイル
 実行ファイル名を指定してコンパイル gcc -o 実行ファイル ソースファイル

高専プロコンin群馬大会-本戦参加3チーム

4EIの創造工学演習の授業にて作成しているシステム開発にて高専プロコンin群馬に応募していましたが、下記3チームが無事書類審査を通過し、10月15日(土),16日(日)に開催される本戦に参加することとなりました。また、3EIのグループによる競技部門についても、本戦参加も決定となりました。

課題部門

  • 「お神輿わっしょい – 自宅でお神輿担ぎを疑似体験 – 」4EI:出倉、越元、小見山、ヤン

  • 「PaOn – 子供に身近な公園を自宅に! – 」4EI:泉、伊藤、並河、松田、山岸、清水

自由部門

  • 「妄想サイクリング – 観客を巻き込む VRフィットネスゲーム – 」4EI:戸田、中村、吹谷、武藤

システム

最新の投稿(電子情報)

アーカイブ

カテゴリー