使用awk组合多个文本文件

时间:2014-08-14 02:22:39

标签: awk

我在文本文件中保存了一些微小的统计数据,并命名为1min.txt,2min.txt等。

1min.txt
F1,21
F2,32
F3,22

2min.txt
F2,12
F4,32

我想以下列格式组合这些文件:

combined.txt
Field   1min    2min
F1      21      0
F2      32      12
F3      22      0
F4      0       32

某些文件中可能不存在某些字段,并且将为这些字段输入0。

我尝试使用awk但是找不到简单的方法。有人可以帮忙吗?

由于

5 个答案:

答案 0 :(得分:3)

使用awk

awk -F, '
!seen[FILENAME]++ { 
    fname[++numFile] = FILENAME 
}
{
    flds[$1]++;
    map[FILENAME,$1] = $2
}
END {
    printf "%-10s", "FIELD";
    for (cnt=1; cnt<=numFile; cnt++) {
        file = fname[cnt];
        sub (/.txt/, "", file);
        printf "%-10s", file; 
    }
    print ""; 
    for (fld in flds) { 
        printf "%-10s", fld; 
        for (cnt=1; cnt<=numFile; cnt++) {
            printf "%-10s", map[fname[cnt],fld]+0
        }
        print "";
    }
}' 1min.txt 2min.txt

输出:

FIELD      1min       2min      
F1         21         0         
F2         32         12        
F3         22         0         
F4         0          32     

查看输出后,可以将输出重定向到另一个文件。您可以根据需要在最后传递尽可能多的文件。如果你有太多的话,你甚至可以使用shell glob,例如:*.txt

注意:我无法保证字段的顺序,因为它们并不总是出现在所有文件中。

这是一个纯粹的有趣perl japh,它将做同样的事情:

perl -F, -lane'
$f{$ARGV}++; $h{$F[0]}
{$ARGV}=      $F[  1  ]
}{print       join"\t",
"FIELD",      map{s/.[tx]+
//x           ;$_}sort{$a
<=>$b}        keys%f;print
join"\n",    map{$f
=$_;         join
"\t",  $f,map
{$h{$f
}{$_}
//=0}
sort{$a
<=>$b}
keys%f
}sort
keys%h;
' *.txt

输出:

FIELD   1min    2min
F1      21      0
F2      32      12
F3      22      0
F4      0       32

答案 1 :(得分:1)

$ cat tst.awk
BEGIN { FS=","; OFS="\t" }
{ keys[$1]; val[$1,NR==FNR] = $2 }
END {
    print "Field", "1min", "2min"
    for (key in keys) {
        print key, val[key,1]+0, val[key,0]+0
    }
}

$ awk -f tst.awk 1min.txt 2min.txt
Field   1min    2min
F1      21      0
F2      32      12
F3      22      0
F4      0       32

如果您关心输出订单,请告诉我们您要查找的订单 - 在两个文件或字母或其他内容中查看密钥的顺序。如果它是他们被看到的顺序那么那就是:

$ cat tst.awk
BEGIN { FS=","; OFS="\t" }
!seen[$1]++ { keys[++numKeys] = $1 }
{ val[$1,NR==FNR] = $2 }
END {
    print "Field", "1min", "2min"
    for (k=1; k<=numKeys; k++) {
        key = keys[k]
        print key, val[key,1]+0, val[key,0]+0
    }
}

答案 2 :(得分:1)

使用join

join -t , input1 input2 -j 1 -o "0 1.2 2.2" -e 0 -a1 -a2 | column -t -s,

给出:

F1  21  0
F2  32  12
F3  22  0
F4  0   32

添加标题:

join -t , input1 input2 -j 1 -o "0 1.2 2.2" -e 0 -a1 -a2 | \
     sed '1iField,1min,2min' | column -t -s,

结果如下:

Field  1min  2min
F1     21    0
F2     32    12
F3     22    0
F4     0     32

答案 3 :(得分:0)

Awk允许您显式读取文件,因此您可以根据需要将所有逻辑放在BEGIN部分中。这是一个例子:

awk -F, '
  BEGIN {
    while (getline <"1min.txt") {
      field[$1]=1
      a1[$1]=$2
    }
    while (getline <"2min.txt") {
      field[$1]=1
      a2[$1]=$2
    }
    print "Field\t1min\t2min"
    for (x in field) {
      print x"\t"(a1[x]+0)"\t"(a2[x]+0)
    }
  }
'

答案 4 :(得分:0)

我已经编写了一些python代码来解决你的问题。

fh_1 = open("1min.txt", "r")
fh_2 = open("2min.txt", "r")
fh_3 = open("combine.txt", "w")

min_c_1 = {}
min_c_2 = {}

lines_of_text = ["Field   1min    2min\n"]

for l1 in fh_1.readlines():
    data = l1.split(',')
    min_c_1[data[0]] = data[1].rstrip()

for l1 in fh_2.readlines():
    data = l1.split(',')
    min_c_2[data[0]] = data[1].rstrip()

for key in min_c_1.keys():
    if key in min_c_2.keys():
        msg = str(key) + "      " + str(min_c_1[key]) + "      " +  str(min_c_2[key]) + "\n"
        lines_of_text.append(msg)
        del min_c_2[key]
    else:
        msg = str(key) + "      " + str(min_c_1[key]) + "      0" + "\n"
        lines_of_text.append(msg)

for key in min_c_2.keys():
    msg = str(key) + "      0" + "       " + str(min_c_2[key]) + "\n"
    lines_of_text.append(msg)

fh_3.writelines(lines_of_text)

fh_1.close()
fh_2.close()
fh_3.close()

如果没有用,请告诉我。