从复杂的文件结构中提取数据

从复杂的文件结构中提取数据

我有一个 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 个字段。前面几行显示了该数据库的两条记录的转储。空行代表数据库中的空白字段。

第一个字段 (F0) 是您看到的数字 1500、1501...

第二个字段 (F1) 是日期,格式为日、月、年。

字段F2、F3、F4、F5、F6、F7是六个整数。

我需要的是从该文件中提取 F0、F2、F3、F4、F5、F6、F7,为每个文件创建一行。

鉴于上述两条记录,最终文件将是

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

我知道如何使用长达数英里的 bash 脚本来做到这一点,并且在每一行上进行交互,等等。但我也知道 unix 是一堆技巧,特别是命令sed,这可能可以用简单的一行来完成。我喜欢学习新东西,所以请教各位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

GNUsed有一个很好的扩展来匹配给定行之后的第 n 行,这在这里很有用。它不能在 OSX 上运行,但为了它的乐趣:

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

答案2

这是一种方法:

$ 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

解释:

  • -000:激活“段落模式”,它将perl字段分隔符设置为\n\n连续换行符。这意味着它将把您的每条记录视为一行。

  • @f=split(/\n/);:按换行符分割当前行(记录)并保存为数组@f。该数组现在包含记录中的每个字段。这意味着数组切片@f[0,2..8]将包含字段 0 和 2 到 8。

  • print join ",",@f[0,2..8] , "\n"':这将用逗号连接数组切片,并打印结果字符串,后跟换行符。

答案3

如果您的数据始终存在一定数量的缺失字段(IE记录之间有 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

相关内容