ABOUT

イベント・勉強会

Tech LION

USP Magazine

外部サイト

Twitter

 前へ
 次へ
投稿者: かいちょう   2012年2月12日 14:56    タグ: シェルスクリプト bash read /dev/stdin

シェルスクリプトでの標準入力の読み方

 友の会のページにあまりにもシェルスクリプトの情報が少ないので反省している会長です。
 先日、あるサイトで、「シェルスクリプトで標準入力を読むためにはreadコマンドを使う」ということを書いてあったのですが、ちょっと補足が必要だと思いました。
 確かに、下のようにreadを使うと、標準入力を読むことができます。
ueda@uedaubuntu:~$ cat hoge.sh 
#!/bin/bash

while read i ; do
	#数字を読み込んで1足して出力する。
	echo $((i+1))
done
 実行するとこうなりますね。
ueda@uedaubuntu:~$ seq 1 10 | ./hoge.sh 
2
3
4
5
6
7
8
9
10
11

/dev/stdinを使おう

 でも、この方法は一番最後に、どうしようもないときにとるべき手段です。同じ機能を持つシェルスクリプトは、以下のように書くこともできます。シェルスクリプトというよりawkのスクリプトですが・・・。
ueda@uedaubuntu:~$ cat hoge2.sh 
#!/bin/bash

awk '{print $1+1}' < /dev/stdin
「< /dev/stdin」が、標準入力からのリダイレクトになります。 この例の場合はawkの使い方を知っている必要がありますが、 論点はそのようなことではなく、
  • bashの変数に一行一行読み込むのは時間計算量の点で高コスト
  • 行を変数に入れてしまうとその後コマンドでバッチ処理が行いにくくなる
  • 別に/dev/stdinを使うことに比べて体裁がよいわけではない
  • という点にあります。計算量については、ちょっとしたことをするには問題にはなりません。 が、私ならびに友の会としては、「シェルスクリプトは遅い」といういわれのない評判につながるので無視できない問題ではあります。

    コストは桁違い

     さきほどのhoge.shとhoge2.shの時間を比較してみましょう。
    ueda@uedaubuntu:~$ time seq 1 1000000 | ./hoge.sh > /dev/null
    
    real	0m29.642s
    user	0m24.542s
    sys 	0m5.992s
    ueda@uedaubuntu:~$ time seq 1 1000000 | ./hoge2.sh > /dev/null
    
    real	0m1.024s
    user	0m1.516s
    sys 	0m0.024s
    
    というように、ざっと30倍弱の差がついてしまいます。100万行というとデータ処理ではざらにある数字なので、この違いは無視できません。

    readを使う場合

     私の場合は、シェルスクリプトに対する標準入力を読む目的でreadを使ったことがありませんが、スクリプト中で次のような使い方をすることはあります。  
    ls file.*	|
    while read f ; do
    	mv ${f} ${f}.old
    done
    
    ただしこのように書くのも、せいぜいファイル数が100程度の場合で、それよりも多い場合はmanでいろいろ調べながらxargsなどで置き換えます。lsもechoに置き換えます。

    まとめ!

     ちょっと「~するべからず」調で書いてしまいましたが、以下のことをおさえておけばreadを使ってもかまわないでしょう。
    標準入力の読み込みにreadを使うのは/dev/stdinからのリダイレクトに比べて高コスト。
    おしまい。

    ↓押してね!

    フリーワード検索

    新着情報

    タグ

    人気ページ 2012年2月18日~