マイナー・マイナー

隠れた名作の発掘が生きがい。

【Shell】CSVファイルの行と列を抽出する


スポンサードリンク

CSV形式のファイルから特定の行と列を抽出する方法をまとめました。カンマ区切りのデータからawkとcutを利用して行と列を抜き出します。

f:id:yosinoo:20200913190228p:plain
抽出イメージ

サンプルデータ

sample.csv

a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
a3,b3,c3,d3,e3
a4,b4,c4,d4,e4
a5,b5,c5,d5,e5

行の抽出

3行目を抽出する

awkで行数(NR)に抽出したい行を指定し、行全体($0)を出力します。

awk 'NR == 3 {print $0}' sample.csv

# result
a3,b3,c3,d3,e3

3行目と5行目を抽出する

awkの評価式をORでつなげます。

awk 'NR == 3 || NR == 5 {print $0}' sample.csv

# result
a3,b3,c3,d3,e3
a5,b5,c5,d5,e5

3行目以前を抽出する

awkの評価式を「以下」で指定します。

awk 'NR <= 3 {print $0}' sample.csv 

# result
a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
a3,b3,c3,d3,e3

headで行数指定する方が簡単かもしれないです。

head -n 3 sample.csv 

# result
a1,b1,c1,d1,e1
a2,b2,c2,d2,e2
a3,b3,c3,d3,e3

3行目以降を抽出する

awkの評価式を「以上」で指定します。

awk 'NR >= 3 {print $0}' sample.csv 

# result
a3,b3,c3,d3,e3
a4,b4,c4,d4,e4
a5,b5,c5,d5,e5

最後から抽出したい行数が分かっていればtailで行指定する方が簡単かもしれないです。

tail -n 3 sample.csv 

# result
a3,b3,c3,d3,e3
a4,b4,c4,d4,e4
a5,b5,c5,d5,e5

特定の文字列を含む行を抽出する

awk正規表現によるパターンマッチングが利用できます。行に”4”を含む文字を抽出したい場合は下記のように記述できます。

awk '/4/ {print $0}' sample.csv

# result
a4,b4,c4,d4,e4

grepの方が簡単かもしれない。

grep 4 sample.csv 

# result
a4,b4,c4,d4,e4

列の抽出

3列目を抽出する

cutで区切り文字(-d)にカンマを指定し、切り出し位置(-f)に切り出したい列を指定します。

cut -d , -f 3 sample.csv

# result
c1
c2
c3
c4
c5

awkでも区切り文字(-F)にカンマを指定し、切り出したい位置($*)をprintすれば抽出できます。

awk -F ',' '{print $3}' sample.csv

# result
c1
c2
c3
c4
c5

3列目と5列目を抽出する

cutの切り出し位置をカンマでつなげます。

cut -d , -f 3,5 sample.csv

# result
c1,e1
c2,e2
c3,e3
c4,e4
c5,e5

3列目以前を抽出する

cutの切り出し位置の前にハイフンをつけます。

cut -d , -f -3 sample.csv 

# result
a1,b1,c1
a2,b2,c2
a3,b3,c3
a4,b4,c4
a5,b5,c5

3列目以降を抽出する

cutの切り出し位置の後にハイフンをつけます。

cut -d , -f 3- sample.csv

# result
c1,d1,e1
c2,d2,e2
c3,d3,e3
c4,d4,e4
c5,d5,e5

特定の文字列を含む列を抽出する

簡単な方法が分からず…awkでまず行列を作成し、その行列に対してパターンマッチした要素の列の番号を出力して、あとはcut等で抽出するとかですかね。以下は”d”の文字を含む列の番号を出力するサンプルです。

awk -F ',' '
{
  for (i = 1; i <= NF; i++) arr[NR,i] = $i
}
END {
  for (j = 1; j <= NF; j++) {
    for (i = 1; i <= NR; i++) {
      if (arr[i,j] ~ /d/) {
          print j;
          break;
      } 
    }
  }
} 
' sample.csv

# result
4

行列を抽出する

「行を抽出する」「列を抽出する」のコマンドをパイプで繋げれば、任意の行列が抽出できます。

awk 'NR == 3 || NR == 4 {print $0}' sample.csv | cut -d , -f 3,4

# result
c3,d3
c4,d4