【シェルスクリプトツール作成の基本】自作のシェルスクリプトでパイプを使えるようにする


2022/08/09
蛸壺の技術ブログ|

ちょっとしたことですが、
「自作したシェルスクリプトでもパイプ処理できたらいいな」と思うこともしばしばあります。

Linuxコマンドにおいて、自作のシェルスクリプトをパイプ処理するといえば、「Xargsコマンド」が定石かもしれませんが、今回はXargsコマンドを使わないで、なおかつ簡単にパイプ処理を取り入れる方法を検討してみます。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

自作パイプ処理の仕組み

パイプ処理の基本は、前段のコマンドが実行された結果の標準出力を、それを受け構える後段のコマンドの標準入力として扱うことにあります。

ということで、後段のシェルスクリプトの中で、「直前に実行された処理の標準入力」を、正しく受け取る仕組みが必要になります。

これを可能にするのが、シェルスクリプト中に使われる
『cat -』です。

この
cat -を使うことで、標準出力に送られて、パイプ処理待ちになっているテキストを読み込んで、標準入力として柔軟に利用することができるようになります。

以下ように
1.shというテスト用のシェルスクリプトを作成してみましょう。

            
            #!/bin/bash

if [ -p /dev/stdin ]; then
    echo 'パイプ処理から標準入力!'
    cat -
else
    echo '普通の標準入力!'
    echo "$@"
fi
        
これでもうパイプできるシェルスクリプトとして機能します。

            
            $ chmod +x 1.sh

$ echo 'タコ' | ./1.sh
パイプ処理から標準入力!
タコ

$ ./1.sh 'タコ'
普通の標準入力!
タコ
        
シェルスクリプト内の引数として格納する場合には、

            
            #!/bin/bash

if [ -p /dev/stdin ]; then
    _args=$(cat -)
else
    _args=$@
fi

echo "引数は ${_args} です"
        
ここで、標準出力がパイプラインIOで待機しているかどうかを判定する部分が、if [ -p /dev/stdin ] ...fiの箇所です。

前段からのコマンドからの処理が、現在のプロセスから処理された/別プロセスが開いて処理された、どちらの場合にでも適切に後段の標準入力として受け取れるようになります。


合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

自作スクリプトを作って検証

ものは試しで、以下のようなシェルスクリプトでパイプ処理が正しく行われているか、簡単な計算で確認してみましょう。

            
            #!/bin/bash

if [ -p /dev/stdin ]; then
    _str=$(cat -)
else
    _str=$@
fi

echo "${_str}" | bc -l
        
なおこのスクリプトでは、お手元の環境でbcコマンドが使えるか確認しましょう。

            
            $ chmod +x 2.sh

#パイプ処理OK
$ echo '1+2' | ./2.sh
3

#通常の処理もOK
$ ./2.sh '3*4'
12
        

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集

複数の引数がある場合の処理

引数として受け取った標準入力が、配列形式だった想定の場合、以下のようなスクリプトで処理ができると思います。

            
            #!/bin/bash

if [ -p /dev/stdin ]; then
    _arr=$(cat -)
else
    _arr=$@
fi

sum=0
for i in ${_arr[@]}; do
    sum=$((sum + i))
done

echo $sum
        
これを実行して、単純な配列の和を計算してみましょう。

            
            $ chmod +x 3.sh

#👇通常の引数(配列)
$ ./3.sh 4 7 2 6 -10
9

#👇パイプで与える引数(配列)
$ echo 1 7 3 | ./3.sh
11
        
なんとも不思議な動作を行うシェルスクリプトに感じますが、色々とスクリプト化の際の効率が上がりそうです。

記事を書いた人

記事の担当:taconocat

ナンデモ系エンジニア

主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。

合同会社タコスキングダム|蛸壺の技術ブログ【効果的学習法レポート】シェルスクリプトをこれから学びたい人のためのオススメ書籍&教材特集