Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 使用Bash在多个字段上使用非相等键连接匹配的列?_Linux_Bash_Join_Awk - Fatal编程技术网

Linux 使用Bash在多个字段上使用非相等键连接匹配的列?

Linux 使用Bash在多个字段上使用非相等键连接匹配的列?,linux,bash,join,awk,Linux,Bash,Join,Awk,我知道以前也有人问过类似的问题,但我似乎找不到解决具体问题的办法 我的文件结构如下(col1=ID,col2=time increment,col3=data): 我的目标是根据ID第一次和时间第二次连接这两个文件。但是,还必须添加不相等的时间值,并且数据列(col3)必须放置在输出文件的正确列中 期望输出: 14.000119 0 yes no 14.000119 69 yes 14.000119 70 no 14.000

我知道以前也有人问过类似的问题,但我似乎找不到解决具体问题的办法

我的文件结构如下(col1=ID,col2=time increment,col3=data):

我的目标是根据ID第一次和时间第二次连接这两个文件。但是,还必须添加不相等的时间值,并且数据列(col3)必须放置在输出文件的正确列中

期望输出:

14.000119    0      yes    no    
14.000119    69     yes
14.000119    70            no
14.000119    168    no    
14.000119    169           yes
14.000119    259
14.000119    262
14.000119    431
14.000119    456
14.000119    525
14.000119    888    yes
列是用制表符分隔的。我知道awk或join都有一个解决方案,但我似乎无法正确实现。最接近我的是使用

awk -F\\t '{
o1=$1;o2=$2
$1=$2="";gsub("\t","")
_[o1 FS o2]=_[o1 FS o2] FS $0
} END {
for(i in _) print i,_[i]
}' file1 file2 | sort -k1,1 -k2,2 -n
这给了我:

14.000119       0         yes      no
14.000119       69        yes
14.000119       70        no
14.000119       168       no
14.000119       169       yes
14.000119       259
14.000119       262
14.000119       431
14.000119       456
14.000119       525
14.000119       888       yes

但正如您所看到的,如果file1中同一个键的值为非空,则数据值只能填入正确的列(file2的第四列)。

使用join和一些解决方法解决了这个问题

join -j1 -a 1 -a 2 -e '' -o '0,1.4,2.4' -t $'\t' 
<(<file1 awk -F\\t '{print $1"-"$2 "\t" $0}' | sort -k1,1) 
<(<file2 awk -F\\t '{print $1"-"$2 "\t" $0}' | sort -k1,1) 
| sed 's/-/\t/g' | sort -k1,1 -k2,2 -n
join-j1-a1-a2-e'-o'0,1.4,2.4'-t$'\t'

使用GNU awk表示数组的数组,并将其排序为:

$ cat tst.awk
BEGIN { FS=OFS="\t" }
{ vals[$1][$2][ARGIND] = $3 }
END {
    PROCINFO["sorted_in"] = "@ind_num_asc"
    for (id in vals) {
        for (time in vals[id]) {
            print id, time, vals[id][time][1], vals[id][time][2]
        }
    }
}

$ awk -f tst.awk file1 file2
14.000119       0       yes     no
14.000119       69      yes
14.000119       70              no
14.000119       168     no
14.000119       169             yes
14.000119       259
14.000119       262
14.000119       431
14.000119       456
14.000119       525
14.000119       888     yes

使用
awk
sort
的一点帮助,如何:

awk -F'\t' '
    NR==FNR {a[$1"\t"$2] = $3; next}
    {a[$1"\t"$2] ? a[$1"\t"$2] = a[$1"\t"$2]"\t"$3 : a[$1"\t"$2] = "\t"$3}
    END {for (i in a) print i"\t"a[i]}
' file1 file2 | sort -k1,1n -k2,2n
结果:

14.000119       0       yes     no
14.000119       69      yes
14.000119       70              no
14.000119       168     no
14.000119       169             yes
14.000119       259
14.000119       262
14.000119       431
14.000119       456
14.000119       525
14.000119       888     yes

你能接受这个答案吗(是的,你自己的答案),这样问题的答案就更清楚了。是的,但是有两天的等待期。如果您的真实数据中可以有多个ID,并且包含了给定ID仅出现在文件1中或仅出现在文件2中的情况,那么您应该在示例中提供多个ID。永远不要给变量命名
\uu
顺便说一句-理解变量代表什么比给它命名一个字母更没用!在实际文件中,变量显然没有命名为u,并且具有更多或更少的ID不会导致问题的性质,因为数据无论如何都是在第一列上排序的。谢谢你的回答;这一点也不明显。为什么要将一个变量从有意义的名称重命名为
\uuu
,以便在一个问题中发布,您希望使您的脚本尽可能容易让其他人理解,以便他们能够帮助您?拥有更多的ID与拥有1个ID的问题大不相同,您可能希望以各种方式处理仅出现在1个文件中的ID。例如,在我的回答中,我假设您希望两个文件中的所有ID都以数字顺序显示,但您可能希望忽略一些ID,或者希望一个文件特有的ID显示在开始或结束或其他位置。很好,表示问题已解决的方法是单击复选标记接受答案。(但现在我看到你答案上的评论,你知道这一点。)请不要在你的问题中编辑“已解决”。请不要添加编辑/更新,只需编辑并尽可能地发布文章即可。
awk -F'\t' '
    NR==FNR {a[$1"\t"$2] = $3; next}
    {a[$1"\t"$2] ? a[$1"\t"$2] = a[$1"\t"$2]"\t"$3 : a[$1"\t"$2] = "\t"$3}
    END {for (i in a) print i"\t"a[i]}
' file1 file2 | sort -k1,1n -k2,2n
14.000119       0       yes     no
14.000119       69      yes
14.000119       70              no
14.000119       168     no
14.000119       169             yes
14.000119       259
14.000119       262
14.000119       431
14.000119       456
14.000119       525
14.000119       888     yes