我在文本文件中保存了一些微小的统计数据,并命名为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但是找不到简单的方法。有人可以帮忙吗?
由于
答案 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()
如果没有用,请告诉我。