比较多个tsv文件中的匹配列



我有4466.tsv文件,其结构如下:文件_结构

我想比较4466个文件,看看有多少ID(第一列(匹配。我只发现bash命令有两个文件;comm";。你能告诉我怎么做吗?

谢谢

我把你的问题读成:

在所有TSV文件中,在每个文件中都可以找到哪些列ID?

如果这是真的,我们需要所有文件中所有列ID集的交集。我们可以使用join命令来获得任意两个文件的交集,也可以使用交集的代数性质来有效地连接所有文件。

考虑这三个文件的ID的交集:

file1.tsv   file2.tsv   file3.tsv
---------   ---------   ---------
ID          ID          ID       
1           1           2        
2           3           3        
3                                

"3〃;是三者之间共享的唯一ID。我们一次只能将两个文件连接在一起,所以我们需要一些方法来有效地获得join (join file1.tsv file2.tsv) file3.tsv。幸运的是,交集是幂等关联,所以我们可以在所有文件的循环中迭代应用join,如下所示:

# "Prime" the common file
cp file1.tsv common.tsv
for TSV in file*.tsv; do
join "$TSV" common.tsv > myTmp
mv myTmp common.tsv
echo "After joining $TSV, common IDs are:"
cat common.tsv
done

当我运行它时,它会打印以下内容:

After joining file1.tsv, common IDs are:
ID
1
2
3
After joining file2.tsv, common IDs are:
ID
1
3
After joining file3.tsv, common IDs are:
ID
3
  1. 第一次迭代将file1与自身连接起来(因为我们用file1启动了common(;这就是我们交集为幂等的地方
  2. 第二次迭代加入file2;2〃
  3. 第三次迭代加入file3,将ID缩减为"0";3〃

从技术上讲,join考虑字符串";ID";成为要评估的事情之一。。。它不知道标题行是什么,也不知道ID是什么…它只知道在一些字段中查找公共值。在那个例子中,我们没有指定字段,所以它默认为第一个字段,并且它总是找到";ID";它总是发现";3〃;。

对于您的文件,我们需要告诉加入:

  • 在制表符上分隔,带有-t<TAB-CHAR>
  • 只输出联接字段(默认情况下,它是第一个字段(,-o为0

以下是我的完整实现:

#!/bin/sh
TAB="$(printf 't')"
# myJoin joins tsvX with the previously-joined common on 
# the first field of both files; saving the the first field
# of the joined output back into common
myJoin() {
tsvX="$1"
join -t "$TAB" -o 0 common.tsv "$tsvX" > myTmp.tsv
mv myTmp.tsv common.tsv
}
# "Prime" common
cp input1.tsv common.tsv
for TSV in input*.tsv; do
myJoin "$TSV"
done
echo "The common IDs are:"
tail -n -1 common.tsv

要了解"$(printf 't')"的原因,请查看以下POSIX合规性:

  • https://www.shellcheck.net/wiki/SC3003
  • https://unix.stackexchange.com/a/468048/366399
这个问题听起来很含糊。因此,假设您想要提取所有4466个文件都有共同的ID,即每个ID在*.tsv文件的中至少出现一次,则可以在纯Bash中使用关联数组并计算它们的"集交集"来实现这一点(例如(。
#!/bin/bash
# removes all IDs from array $1 that do not occur in array $2.
intersect_ids() {
local -n acc="$1"
local -rn operand="$2"
local id
for id in "${!acc[@]}"; do
((operand["$id"])) || unset "acc['${id}']"
done
}
# prints IDs that occur in all files called *.tsv in directory $1.
get_ids_intersection() (
shopt -s nullglob
local -ar files=("${1}/"*.tsv)
local -Ai common_ids next_ids
local file id _
if ((${#files[@]})); then
while read -r id _; do ((++common_ids["$id"])); done < "${files[0]}"
for file in "${files[@]:1}"; do
while read -r id _; do ((++next_ids["$id"])); done < "$file"
intersect_ids common_ids next_ids
next_ids=()
done
fi
for id in "${!common_ids[@]}"; do printf '%sn' "$id"; done
)
get_ids_intersection /directory/where/tsv/files/are

相关内容

  • 没有找到相关文章

最新更新