はじめに
必要なデータが例えば以下のように整備されているといいのですが
textA,numA textB,numB ...
以下のような状態であることがあります。
textA numA hogeA textB numB hogeB ...
要は3行毎に情報が繰り返され、1行目と2行目をカンマ区切りで一行として扱いたい。これらを例にデータを整備(データクレンジング)する流れについて簡単に説明します。
コマンド実行環境
- Debian GNU/Linux 9 (stretch)
ワンライナー
以下で3行毎のデータをCSVで扱えます。
# cat hoge.txt | awk 'ORS=NR%3?",":RS'
スクリプトでの処理方針
繰り返し部分
例えば以下のように書けば$iが1~10まで順々に値が入っていくので
for i in `seq 1 10`
3行毎の繰り返すが10セットあれば$i*3 -2
でtextが、$i*3-1
でnumの情報が格納されている行が取得できます。
以下のロジックを使えば特定行の数値を取れるので
例えばシェルスクリプトにて以下のようにすれば
for i in `seq 1 10` do a=`expr $i \* 3 - 2` b=`expr $i \* 3 - 1` x=`cat hoge.txt | head -n $a | tail -n 1` y=`cat hoge.txt | head -n $b | tail -n 1` z=$x","$y echo $z done
textA,numAといった形で出力されます。
セット数の取得部分
手動で10と入れましたが、ここもテキストによって自動的に取りたいです。
空行がない前提であれば、wl -l
にて行数が取得できます。
n=`cat hoge.txt | wc -l` m=`expr $n / 3` for i in `seq 1 $m` ...
複数行毎に繰り返すテキストを処理するスクリプト
以下のスクリプトを実行すれば
#!/bin/bash n=`cat hoge.txt | wc -l` m=`expr $n / 3` for i in `seq 1 $m` do a=`expr $i \* 3 - 2` b=`expr $i \* 3 - 1` x=`cat hoge.txt | head -n $a | tail -n 1` y=`cat hoge.txt | head -n $b | tail -n 1` z=$x","$y echo $z done
出力結果は以下となります。
textA,numA textB,numB ...
終わりに
大量データの整備はシェルで捌くことが多いですが、できるだけ汎用的な方法で処理する流れを記載しました。
ご参考になれば幸いです。