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