我有以下代码将多个文件连接在一起。它工作正常,但我想将空值替换为0,所以我使用-e“0”。但它不起作用。 有什么想法吗?
for k in `ls file?`
do
if [ -a final.results ]
then
join -a1 -a2 -e "0" final.results $k > tmp.res
mv tmp.res final.results
else
cp $k final.results
fi
done
示例:
file1:
a 1
b 2
file2:
a 1
c 2
file3:
b 1
d 2
Results:
a 1 0 1 0
b 2 1 0
c 2
d 2
expected:
a 1 1 0
b 2 0 1
c 0 2 0
d 0 0 2
答案 0 :(得分:6)
另外,GNU版本的join支持-o auto
。 -e
和-o
引起了足够的挫败感,让人们学习awk。 (另见How to get all fields in outer join with Unix join?)。正如cmh所说:它没有记录,但是当使用加入时,-e
选项只能与-o
选项一起使用。
一般解决方案:
cut -d ' ' -f1 file? | sort -u > tmp.index
for k in file?; do join -a1 -e '0' -o '2.2' tmp.index $k > tmp.file.$k; done
paste -d " " tmp.index tmp.file.* > final.results
rm tmp*
额外奖励:如何比较git中的多个分支?
for k in pmt atc rush; do git ls-tree -r $k | cut -c13- > ~/tmp-branch-$k; done
cut -f2 ~/tmp-branch-* | sort -u > ~/tmp-allfiles
for k in pmt atc rush; do join -a1 -e '0' -t$'\t' -11 -22 -o '2.2' ~/tmp-allfiles ~/tmp-branch-$k > ~/tmp-sha-$k; done
paste -d " " ~/tmp-allfiles ~/tmp-sha-* > final.results
egrep -v '(.{40}).\1.\1' final.results # these files are not the same everywhere
答案 1 :(得分:5)
文档记录不佳,但使用join
时,-e
选项仅与-o
选项一起使用。每次循环时都需要修改订单字符串。以下代码应生成所需的输出。
i=3
orderl='0,1.2'
orderr=',2.2'
for k in $(ls file?)
do
if [ -a final.results ]
then
join -a1 -a2 -e "0" -o "$orderl$orderr" final.results $k > tmp.res
orderl="$orderl,1.$i"
i=$((i+1))
mv tmp.res final.results
else
cp $k final.results
fi
done
正如你所看到的,它开始变得凌乱。如果你需要进一步扩展这一点,可能值得推迟使用更强大的工具,如awk或python。
答案 2 :(得分:1)
假设单个文件中没有重复的密钥且密钥不包含空格,则可以使用gawk
和已排序的文件全局。对于大型文件,这种方法非常快,并且与所有数据的全局相比,仅使用相对少量的内存。像:
gawk -f script.awk $(ls -v file*)
script.awk
的内容:
BEGINFILE {
c++
}
z[$1]
$1 in a {
a[$1]=a[$1] FS ($2 ? $2 : "0")
next
}
{
for(i=1;i<=c;i++) {
r = (r ? r FS : "") \
(i == c ? ($2 ? $2 : "0") : "0")
}
a[$1]=r; r=""
b[++n]=$1
}
ENDFILE {
for (j in a) {
if (!(j in z)) {
a[j]=a[j] FS "0"
}
}
delete z
}
END {
for (k=1;k<=n;k++) {
print b[k], a[b[k]]
}
}
测试输入/ grep . file*
的结果:
file1:a 1
file1:x
file1:b 2
file2:a 1
file2:c 2
file2:g
file3:b 1
file3:d 2
file5:m 6
file5:a 4
file6:x
file6:m 7
file7:x 9
file7:c 8
结果:
a 1 1 0 4 0 0
x 0 0 0 0 0 9
b 2 0 1 0 0 0
c 0 2 0 0 0 8
g 0 0 0 0 0 0
d 0 0 2 0 0 0
m 0 0 0 6 7 0
答案 3 :(得分:0)
我放弃了使用join并以其他方式编写了我的脚本
keywords=`cat file? | awk '{print $1}' | sort | uniq | xargs`
files=`ls file? | xargs`
for p in $keywords
do
x=`echo $p`
for k in $files
do
if grep -q ^$p $k
then
y=`cat $k | grep ^$p | awk '{print $2}'`
x=`echo $x $y`
else
echo $p $k
x=`echo $x 0`
fi
done
echo $x >> final.results
done