给定文件:
1.txt
1, abc, 123, 456, 789
2, lmn, 123, 456, 789
3, pqr, 123, 456, 789
2.txt
1, abc, 123, 000, 000
3, lmn, 123, 000, 000
9, opq, 123, 000, 000
输出.txt
ID, NAME, X, 1A, 1B, 2A, 2B
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000
我用过这以供参考。
我尝试使用以下内容:
join -t , -a1 -a2 -1 1 -2 1 -o 0 -o 1.2 -o 1.3 -o 1.4 -o 1.5 -o 2.4 -o 2.5 -e "MISSING" 1.txt 2.txt
其产生:
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789,MISSING,MISSING
3, pqr, 123, 456, 789, 000, 000
9,MISSING,MISSING,MISSING,MISSING, 000, 000
有什么帮助吗?
答案1
我认为你一个人无法做到这join
一点。你可以这样做:
join -t, -a1 -a2 -o0,1.2,1.3,1.4,1.5,2.2,2.3,2.4,2.5 -e MISSING 1.txt 2.txt |
perl -F, -lape '@F[1..2]=@F[5..6] if $F[1] eq "MISSING";
$_=join",",@F[0..4],@F[7..8]'
-p
:使用像 sed/awk 中那样的逐行读取循环-a
,-F,
:像 awk 一样,将行分割成字段(放入@F
数组中)。-l
:作用于行的内容(类似于在( )awk
上分割输入(但不包含在) 中,并且( ) 在打印之前附加)。RS
$/
RS
$0
ORS
$\
-e ...
: perl [e] 表达式来评估每一行。- 然后它读起来几乎像英语:如果字段 1(索引从 0 开始的第二个字段)为“MISSING”,则字段 1 到 2 将设置为字段 5 到 6。然后将当前记录的内容($_就像awk中的$0)设置到字段0到4和7到8。
实际上,编写相同的内容awk
并不复杂:
awk -F, -vOFS=, '$2 == "MISSING"{$2=$6;$3=$7}
{print $1,$2,$3,$4,$5,$8,$9}'
答案2
仅使用 awk:
awk -F, -v OFS=, '
BEGIN {m = " MISSING"}
# process file1
NR == FNR {lines[$1] = $0; next}
# process file2
{
added[$1] = $4 OFS $5
if (!($1 in lines)) {
$4 = m
$5 = m
lines[$1] = $0
}
}
# print the combined output
END {
for (id in lines) {
if (!(id in added))
added[id] = m OFS m
print lines[id], added[id]
}
}
' 1.txt 2.txt | sort -n
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000
答案3
听起来您想加入前三个领域。然后,您应该在新的第一个字段上更改前两个分隔符join
,然后恢复分隔符:
join -t, -j1 -a1 -a2 -o 0 1.2 1.3 2.2 2.3 -e " MISSING" \
<(sed 's/, /\x02/;s/, /\x02/' 1.txt) <(sed 's/, /\x02/;s/, /\x02/' 2.txt) \
| sed 's/\x02/, /g'
回报
1, abc, 123, 456, 789, 000, 000
2, lmn, 123, 456, 789, MISSING, MISSING
3, pqr, 123, 456, 789, 000, 000
9, opq, 123, MISSING, MISSING, 000, 000