忍者ブログ

プログラミングの練習

プログラミングの問題やプログラミング関連知識、ソフトウェアのテストについてのブログです

【Bash】2つのファイルを同時に1行ずつ並行処理する方法|exec とファイル記述子(3< , 4<)の活用

Bashで複数ファイルの行を突き合わせたり並行して処理したりしたい場合、ファイル記述子(ファイルディスクリプタ)を複数割り当てる手法が非常に有効です。

今回は exec 3<file1 と exec 4<file2 を使い、2つのテキストファイルを同時に1行ずつ読み込んで処理する具体的なスクリプトと注意点を解説します。





1. サンプルコードと実行結果

2つの入力ファイルからそれぞれの行を同時に読み込み、セットで整形出力するスクリプトです。


  • ① 準備するテキストファイル

    # file1.txt(サーバー名リスト)

    server-A

    server-B

    server-C



    # file2.txt(IPアドレスリスト)

    192.168.1.10

    192.168.1.20

    192.168.1.30

  • ② ソースコード(parallel_read.sh)

    #!/bin/bash



    # ファイル記述子 3 と 4 にファイルを割り当て

    exec 3< file1.txt

    exec 4< file2.txt



    # どちらか一方の読み込みが成功する限りループ継続

    while true; do

      IFS= read -u3 -r line1

      res1=$?

      IFS= read -u4 -r line2

      res2=$?



      # 両方のファイルが終端(EOF)に達したらループを抜ける

      if [ $res1 -ne 0 ] && [ $res2 -ne 0 ]; then

        break

      fi



      echo "Host: ${line1:-N/A} | IP: ${line2:-N/A}"

    done



    # ファイル記述子を明示的にクローズ

    exec 3<&-

    exec 4<&-

  • ③ 実行結果

    $ ./parallel_read.sh

    Host: server-A | IP: 192.168.1.10

    Host: server-B | IP: 192.168.1.20

    Host: server-C | IP: 192.168.1.30



2. スクリプトの仕組みと重要ポイント

複数ファイルを同時に扱う際の技術的ポイントを解説します。


  • Point:ファイル記述子の個別管理と終了判定

    ・exec 3< file1 / exec 4< file2:番号「3」と「4」のファイル記述子を独立してオープンします。

    ・read -u3 / read -u4:それぞれの記述子から1行ずつ個別に読み取ります。

    ・終了ステータス($?)の判定:read コマンドはファイルの終端(EOF)に達すると 0 以外の返り値を出力します。両方の変数が非0になった段階でループを抜ける構成にしています。

    ・後処理(exec 3<&-):使い終わった記述子を明示的に解放することで、リソースリークを防ぐ安全な実装になります。

【解説と補足ポイント:行数が異なる場合の対策(デフォルト値設定)】



■ 行数が揃っていない場合の安全策

2つのファイルの行数が異なる場合(片方が4行で片方が3行など)、片方がEOFに達すると空文字("")が読み込まれます。



スクリプト内ではパラメータ展開の構文 ${line1:-N/A} を使うことで、行が不足している場合に任意の値(この例では N/A)を自動挿入できます。これにより、行数のズレによるエラーや表示崩れを防止可能です。



3. まとめ

Bashで複数テキストファイルを同時に並行読み込みする場合は、exec 3< ... と read -u の組み合わせが最も確実で柔軟な方法です。


ログや設定値の突き合わせ処理、2つのリストを連携させた一括自動化スクリプトなどで非常に重宝するテクニックです。


PR