複雑なファイル構造からデータを抽出する

複雑なファイル構造からデータを抽出する

データベースダンプであり、1行に1つのエントリを含むtxtファイルがあります。構造は次のとおりです。

1500
29/03/2010 
18
02
09
47
17
45
28.248
0
0.01
130
12.721
7908
298,809
YES
3.046.550,39
6.500.000,00
17,444,222


1501
30/03/2010
27
54
28
50
22
03
37.223
0
0.00
97
22,466
7379
421.90
NO
20,262,429
25,000,000.01
17,995,281.33


... the third record starts here

データベースには21のフィールドが含まれています。前の行は、このデータベースの2つのレコードダンプを示しています。空の行は、データベースの空のフィールドを表します。

最初のフィールド(F0)は1500、1501...

2番目のフィールド(F1)は、日、月、年の形式の日付です。

フィールドF2、F3、F4、F5、F6、およびF7は6つの整数です。

私にとって必要なのは、このファイルからF0、F2、F3、F4、F5、F6、F7を抽出して各ファイルの行を作成することです。

上記の2つのレコードが与えられた場合、最終ファイルは次のようになります。

1500,18,02,09,47,17,45
1501,27,54,28,50,22,03

私は数マイルに達するbashスクリプトを使用してこれを行い、すべての行で対話する方法などを知っています。しかし、私はUnixが多くのトリック、特にコマンドであることを知っており、sedこれはおそらく単純な1行で行われます。私は新しいことを学ぶのが好きなので、UNIXの修道士たちにどうすればいいのか見てみたいです。

私はOSX Mavericksを使用しています。ありがとうございます。

答え1

使用awk:

awk '
  BEGIN {
    fields[1]
    fields[3]
    fields[4]
    fields[5]
    fields[6]
    fields[7]
    last_field=8
  }
  ( NR%21 in fields ) { printf($0",") }
  NR%21==last_field' in_file.txt

または、より良い方法は次のとおりです。

awk '
  NR%21 ~ /^(1|3|4|5|6|7)$/ { printf($0",") }
  NR%21==8' in_file.txt

GNUには、sed与えられた行の後のn行目に一致する素晴らしい拡張機能があります。これはここで便利です。 OSXでは動作しませんが、楽しみのために次のことを行います。

sed -n '
  1~21 { h }
  3~21,7~21 { H }
  8~21 { H; g; s/\n/,/gp }' in_file

答え2

1つの方法は次のとおりです。

$ perl -000ne '@f=split(/\n/); print join(",",@f[0,2..7]) , "\n"' file.txt  
1500,18,02,09,47,17,45
1501,27,54,28,50,22,03

説明する:

  • -000perl:フィールド区切り文字を連続した改行に設定する短絡モードを有効にします\n\n。これは、各レコードを行として扱うことを意味します。

  • @f=split(/\n/);:現在の行(レコード)を改行文字で分割して配列として保存します@f。配列にはレコードのすべてのフィールドが含まれます。これは、配列フラグメントに@f[0,2..8]フィールド0と2〜8が含まれることを意味します。

  • print join ",",@f[0,2..8] , "\n"':配列フラグメントをコンマで連結し、結果の文字列を印刷してから改行文字を印刷します。

答え3

データに常に特定の数の欠落フィールドがある場合(つまりレコード間に2つ以上のハードリターンがある場合)、単に次のことができます。

$ awk -v RS="\\n{2,}" -F"\\n" -v OFS="," '{print $1, $3, $4, $5, $6, $7, $8}' file.txt
1500,18,02,09,47,17,45
1501,27,54,28,50,22,03

関連情報