テキスト処理 - cshellとawkを使用した抽出

テキスト処理 - cshellとawkを使用した抽出

ファイル全体でランダムに繰り返される次の行を含む非常に長いファイルがあります。

$CROSS_BEAM_PROPERTY_281
POINT,201656,,-41.0213,-1.00928
POINT,201657,,-37.8216,-4.15746
POINT,201658,,-5.40451,-51.3106
POINT,201659,,-4.24517,-52.0837
POINT,201660,,-1.74418,-53.1687
POINT,201661,,2.03505,-51.2474
SET3,9,POINT,201670,201683,THRU,201701,201682
PBMSECT,1501,150,CP
        OUTP=8,
        BRP=9,
        T=1.3,
        T(1)=[1.3,PT=(201656, 201657)],
        T(2)=[1.3,PT=(201657, 201658)],
$CROSS_BEAM_PROPERTY_109
POINT,201660,,-1.74418,-53.1687
POINT,201661,,2.03505,-51.2474
POINT,201662,,4.249589,-48.9936
POINT,201663,,7.70361,-48.5562
POINT,201664,,9.169905,-48.7962
POINT,201665,,30.79493,-53.7184
POINT,201666,,33.52191,-53.1064
POINT,201667,,27.54975,-45.6262
PBMSECT,1500,150,CP
        OUTP=6,
        BRP=7,
        T=1.3,
        T(1)=[1.3,PT=(201610, 201611)],
        T(2)=[1.3,PT=(201611, 201612)],

それぞれについて、4番目と5番目の列を変数の配列に抽出して、一度にさらに処理できるようにしますかCROSS_BEAM_PROPERTYPOINTcshell awkまたはsedを使用して抽出するには?

編集:単なる概要です。テキストファイルにはxとyに定義された多くの場所がCROSS_BEAM_PROPERTY_XXあります。POINT上記の例は、2つのビーム属性を持つファイルの一部です。CROSS_BEAM_PROPERTY_XX4番目の列を配列に保存したいです。配列を使用すると、いくつかの追加計算を実行して、配列の最大値、最小値、または合計値を抽出できます。

4番目の列をすべて抽出し、以下の行を使用して要約しました。

cat $file | awk -F ',' '$1 == "POINT" {sum += $4} END {print sum}'

POINTただし、これはテキストファイル内のすべての項目のうち4番目の列の合計です。それぞれは分離されませんCROSS_BEAM_PROPERTY_XX。合計に加えて、4列目の各値の最大値と最小値も決定したいので、CROSS_BEAM_PROPERTY配列が必要です。

希望の出力:

-88.20171
113.280564

次のように、4番目の列の最大値の目的の出力も取得できますか?

2.03505
33.52191

答え1

 cat $file | awk -F "," '/^\$CROSS/,/^PBMSECT/{if($0~/CROSS/){v=$0};if($0~/^POINT/){p[v]+=$4}}END{for(i in p){print p[i]}}'

これにより、最初の要求の出力が印刷されます。

-88.20171
113.280564

要求された2番目の出力の場合は、次のようになります。

cat $file | awk -F "," '/^\$CROSS/,/^PBMSECT/{if($0~/CROSS/){v=$0};if($0~/^POINT/){if($4>p[v]){p[v]=$4}}}END{for(i in p){print p[i]}}'

出力データをより良くするために、出力にcross_beam_propertyを含めることができます。

$ cat $file | awk -F "," '/^\$CROSS/,/^PBMSECT/{if($0~/CROSS/){v=$0};if($0~/^POINT/){p[v]+=$4}}END{for(i in p){printf("%s\t%f\n", i, p[i])}}'
$CROSS_BEAM_PROPERTY_281        -88.201710
$CROSS_BEAM_PROPERTY_109        113.280564

答え2

あなたの説明によれば、正確に何を探しているのかわかりませんが、POINT各行の4番目と5番目の列を取得するには、次のように簡単に実行できますsed

sed -n -e 's/^POINT,[^,]*,[^,]*,//p' data.csv

これにより、サンプルデータから次の出力が生成されます。

-41.0213、-1.00928
-37.8216、-4.15746
-5.40451、-51.3106
-4.24517、-52.0837
-1.74418、-53.1687
2.03505,-51.2474
-1.74418、-53.1687
2.03505,-51.2474
4.249589,-48.9936
7.70361,-48.5562
9.169905,-48.7962
30.79493,-53.7184
33.52191,-53.1064
27.54975,-45.6262

このデータを配列に入れるには、次のように手続き型置換を使用できます。

set array=`sed -n -e 's/^POINT,[^,]*,[^,]*,//p' data.csv`

arrayその後、変数を介してこのデータにアクセスできます。たとえば、次のようになります。

foreach point (${array})
echo ${point}
end

もちろん、以下を使用して同じことを実行できますawk

awk 'BEGIN{FS=",";OFS=","}/^POINT/{print $4,$5}' data.csv

または単にgrepandを使用してくださいcut

cat data.csv | grep '^POINT' | cut -d, -f4,5

関連情報