Duc*_*uck 5 sed text-processing
我有一个 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
Run Code Online (Sandbox Code Playgroud)
该数据库包含 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
Run Code Online (Sandbox Code Playgroud)
我知道如何使用长达数英里的 bash 脚本来做到这一点,并在每一行上进行交互,等等。但我也知道 unix 是一堆技巧,特别是sed
命令,这可能可以用简单的一行来完成。我喜欢学习新东西,所以我问你们 Unix 中的神,我该怎么做。
我在 OSX Mavericks 上。谢谢。
使用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
Run Code Online (Sandbox Code Playgroud)
或者更好:
awk '
NR%21 ~ /^(1|3|4|5|6|7)$/ { printf($0",") }
NR%21==8' in_file.txt
Run Code Online (Sandbox Code Playgroud)
GNUsed
有一个很好的扩展来匹配给定行之后的第 n 行,这在这里很有用。它不适用于 OSX,但为了它的乐趣:
sed -n '
1~21 { h }
3~21,7~21 { H }
8~21 { H; g; s/\n/,/gp }' in_file
Run Code Online (Sandbox Code Playgroud)
这是一种方法:
$ 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
Run Code Online (Sandbox Code Playgroud)
-000
:激活“段落模式”,它将perl
字段分隔符设置为\n\n
连续换行符。这意味着它将把您的每条记录视为一行。
@f=split(/\n/);
:按换行符分割当前行(记录)并保存为数组@f
。该数组现在包含记录中的每个字段。这意味着数组切片@f[0,2..8]
将包含字段 0 和 2 到 8。
print join ",",@f[0,2..8] , "\n"'
:这将用逗号连接数组切片,并打印结果字符串,后跟换行符。