readコマンドで読み込んだ行からカラムを取り出す方法

2021-05-20Bash,Linux

今迄、 read コマンド を一行ずつで読み込んでくりかえし処理する用途でしか使用していませんでした。
ほんのちょっとだけ突っ込んだ使い方を学んだ。

行をカラム分割する

たとえば以下のような csv から 2 列目と 3 列目の情報を取り出す。

1,2,3,4,5
2,3,4,5,6
3,4,5,6,7
4,5,6,7,8
5,6,7,8,9

今迄のやり方

$ cat report.csv | while read line; do
  c2=$(echo "$line" | cut -d, -f 2)
  c3=$(echo "$line" | cut -d, -f 3)

  echo "$c2"
  echo "$c3"
done

結果は以下の通り

2
3
3
4
4
5
5
6
6
7

もう何が何やら

今回見つけたやり方

$ cat report.csv | while IFS=, read -r c1 c2 c3 _; do
  echo "$c2"
  echo "$c3"
done
  • read コマンドに列の区切り文字を渡す( IFS=, )
  • 列のポジションに該当する変数を列挙する
  • 不要な列位置には _ という変数を指定するのが一般的なようだ。( 意味のない変数
  • 変数には各列の値がセットされる

-r オプションをつけないと、ファイルの行末にバックスラッシュが入っていた場合、改行が無視されてしまう。(なかなか無いケースとは思うが、ハマりたくないので念の為付与しておく。)

更に、先の例の場合、c1 という変数は不要なので、以下のように記述できる。

$ cat report.csv | while IFS=, read -r _ c2 c3 _; do
  echo $c2
  echo $c3
done

ちなみにフィルタリングだけが目的であれば...

ここまで見てきた例はあくまでも while ループ内で複雑なロジックを組みたい場合の方法
ただ 2 列目、3 列目を出力したいだけの場合にはもっと簡単に実現できる。

$ cat report.csv | cut -d, -f2,3 | tr ',' "\n"

2021-05-20Bash,Linux