我有一个非常大的CSV日志文件,其中包含以下字段:
aaa=somedata1,bbb=somedata2,ccc=somedata3,eee=somedata5,hhh=somedata8
aaa=somedata1,ddd=somedata4,fff=somedata6,hhh=somedata8
aaa=somedata1,bbb=somedata2,hhh=somedata8,ggg=somedata9,jjj=somedata11
此文件的问题在于,当没有值时,生成设备甚至不包含“ fieldname =“,因此,由于缺少字段,CSV看起来很混乱(因此,每次字段丢失时,其余字段当前字段将被拖到CSV的左侧)。
我的想法是仅使用AWK提取某些相关的列,而且我需要将其输出到新的CSV中。
例如,在上面的示例中,我想提取包括字段“ aaa”和“ hhh”的所有列,以使新的CSV看起来像这样:
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
但是,我有两个问题:
感谢任何帮助!
-编辑1-
是的,我尝试使用一些单独的AWK命令,如下所示:
awk '{for (i=1;i<=NF;i++) if ($i ~ /aaa/) { print $i}}' > aaa.csv
awk '{for (i=1;i<=NF;i++) if ($i ~ /hhh/) { print $i}}' > hhh.csv
然后尝试使用(当然,我总共有10个我有兴趣提取的不同列,但是出于简洁起见,我在示例中只添加了2个):
paste -d "," aaa.csv hhh.csv > Allcolumns.csv
----编辑2 ----
由于原始文件是一个日志,因此我总共要提取约10个相关的列,因此我确保所有行上都出现了哪些列,而我确实需要这些列。如果有可能它们没有出现在原始文件中,我想最好的做法是使最终文件反映诸如“ aaa,hhh ,, iii”之类的内容。
每当您在数据中包含“标记=值”对时,我都会发现最好首先创建一个数组来保存该映射(tag2val[]
如下所示),然后再按其标记(即名称或键)引用所有值。
在所有Unix机器的任何shell中使用任何awk:
$ cat tst.awk
BEGIN {
FS = OFS = ","
numTags = split("aaa,hhh",tags)
}
{
delete tag2val
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
tag2val[tag] = $i
}
for (i=1; i<=numTags; i++) {
tag = tags[i]
printf "%s%s", tag2val[tag], (i<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk file
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
如果要在每一行上打印所有可能的字段,那么这是一种两遍方法,其中第一遍只是识别每行中的所有可能字段:
$ cat tst.awk
BEGIN {
FS = OFS = ","
}
NR==FNR {
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
if ( !seen[tag]++ ) {
tags[++numTags] = tag
}
}
next
}
{
delete tag2val
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
tag2val[tag] = $i
}
for (i=1; i<=numTags; i++) {
tag = tags[i]
printf "%s%s", tag2val[tag], (i<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk file file
aaa=somedata1,bbb=somedata2,ccc=somedata3,eee=somedata5,hhh=somedata8,,,,
aaa=somedata1,,,,hhh=somedata8,ddd=somedata4,fff=somedata6,,
aaa=somedata1,bbb=somedata2,,,hhh=somedata8,,,ggg=somedata9,jjj=somedata11
如果只想打印所有行中出现的字段,请执行以下操作:
$ cat tst.awk
BEGIN {
FS = OFS = ","
}
NR==FNR {
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
cnt[tag]++
}
next
}
FNR==1 {
for (tag in cnt) {
if ( cnt[tag] == (NR-1) ) {
tags[++numTags] = tag
}
}
}
{
delete tag2val
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
tag2val[tag] = $i
}
for (i=1; i<=numTags; i++) {
tag = tags[i]
printf "%s%s", tag2val[tag], (i<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk file file
hhh=somedata8,aaa=somedata1
hhh=somedata8,aaa=somedata1
hhh=somedata8,aaa=somedata1
如果字段顺序的输出很重要,例如,要保持输入顺序,则只需在第一个块中创建一个数组即可将递增计数映射到每个新标记,如下所示:
$ cat tst.awk
BEGIN {
FS = OFS = ","
}
NR==FNR {
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
if ( !cnt[tag]++ ) {
order[++totTags] = tag
}
}
next
}
FNR==1 {
for (i=1; i<=totTags; i++) {
tag = order[i]
if ( cnt[tag] == (NR-1) ) {
tags[++numTags] = tag
}
}
}
{
delete tag2val
for (i=1; i<=NF; i++) {
tag = $i
sub(/=.*/,"",tag)
tag2val[tag] = $i
}
for (i=1; i<=numTags; i++) {
tag = tags[i]
printf "%s%s", tag2val[tag], (i<numTags ? OFS : ORS)
}
}
$ awk -f tst.awk file file
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
aaa=somedata1,hhh=somedata8
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句