如何连接基于一条共同线的线?
How to concatenate lines based on one line in common?
我有一个制表符分隔的文件,如下所示:
4S2P_1:A 4S2P_1:A
4S2P_1:A 6PXX_1:A
4S2P_1:A 6HB8_1:A
4S2P_1:A 6HOO_1:A
4S2P_1:A 6I5D_1:A
4S2R_1:A 4S2R_1:A
4S2C_1:A 4S2C_1:A
4S2C_1:A 4S2B_1:A
4S2E_1:A 4S2E_1:A
4S2E_1:A 5XB5_1:A
4S2E_1:A 5XBH_1:A
创建文件后,第二列中的序列与第一列中的序列相似。 4S2P_1:A本身与6Q5B_1:A、6PXX_1:A、6HB8_1:A等类似。 4S2R_1:A 只是和自己相似。
我想将文件解析为如下所示:
4S2P_1:A 6PXX_1:A 6HB8_1:A 6HOO_1:A 6I5D_1:A
4S2E_1:A 5XB5_1:A 5XBH_1:A
4S2C_1:A 4S2B_1:A
4S2R_1:A
所以我希望输出的第一列和链接到它的列在一行中用 space 分隔,并使形成的簇按降序排列。
我想用 awk 来做这个。
我试过用这个:
awk -F '\t' '{print *" "}'
但它给了我这个输出:
04S2P_1:A
05DTT_1:A
07ASS_1:A
07AUX_1:A
05HAQ_1:A
05HAP_1:A
05HAR_1:A
开头加0,相似序列不在同一行
通常使用散列来使列表唯一。
#! /bin/bash
declare -A hash
while read -r c1 c2; do
hash[$c1]+=$'\t'"$c2"
done
for key in "${!hash[@]}"; do
printf '%s%s\n' "$key" "${hash[$key]}"
done
缺点是,您失去了原来的排序顺序。但在我看来,你并不关心原来的顺序。如果您想按每行的长度对输出进行排序,您可以选择 question.
的答案之一
这是一个简单的 Awk 脚本,用于将具有相同键的值提升到同一行。
awk ' != prev { if(prev) printf "\n";
prev=; printf "%s", ; next }
{ printf " %s", }
END { if (prev) printf "\n" }' file
要按每条记录的长度排序,你需要在阅读时记住一些东西。上面的代码因其简单性和健壮性(应该适用于任何大小的文件)而很有吸引力,但我们可以让它更复杂一点,在每行前面打印一个排序键,代价是需要将每条完整记录保存在记忆,直到我们知道它的长度。
awk 'function pr () { printf "%i\t", n; printf "%s", a[1];
for(i=2; i<=n; ++i) printf " %s", a[i];
printf "\n"; delete a; n=0 }
!= prev { if (prev) pr(); prev=; a[1]=; n=1; next }
{ a[++n] = }
END { if (n) pr() }' file |
sort -t $'\t' -k1rn |
cut -f2-
我有一个制表符分隔的文件,如下所示:
4S2P_1:A 4S2P_1:A
4S2P_1:A 6PXX_1:A
4S2P_1:A 6HB8_1:A
4S2P_1:A 6HOO_1:A
4S2P_1:A 6I5D_1:A
4S2R_1:A 4S2R_1:A
4S2C_1:A 4S2C_1:A
4S2C_1:A 4S2B_1:A
4S2E_1:A 4S2E_1:A
4S2E_1:A 5XB5_1:A
4S2E_1:A 5XBH_1:A
创建文件后,第二列中的序列与第一列中的序列相似。 4S2P_1:A本身与6Q5B_1:A、6PXX_1:A、6HB8_1:A等类似。 4S2R_1:A 只是和自己相似。
我想将文件解析为如下所示:
4S2P_1:A 6PXX_1:A 6HB8_1:A 6HOO_1:A 6I5D_1:A
4S2E_1:A 5XB5_1:A 5XBH_1:A
4S2C_1:A 4S2B_1:A
4S2R_1:A
所以我希望输出的第一列和链接到它的列在一行中用 space 分隔,并使形成的簇按降序排列。
我想用 awk 来做这个。
我试过用这个:
awk -F '\t' '{print *" "}'
但它给了我这个输出:
04S2P_1:A
05DTT_1:A
07ASS_1:A
07AUX_1:A
05HAQ_1:A
05HAP_1:A
05HAR_1:A
开头加0,相似序列不在同一行
通常使用散列来使列表唯一。
#! /bin/bash
declare -A hash
while read -r c1 c2; do
hash[$c1]+=$'\t'"$c2"
done
for key in "${!hash[@]}"; do
printf '%s%s\n' "$key" "${hash[$key]}"
done
缺点是,您失去了原来的排序顺序。但在我看来,你并不关心原来的顺序。如果您想按每行的长度对输出进行排序,您可以选择 question.
的答案之一这是一个简单的 Awk 脚本,用于将具有相同键的值提升到同一行。
awk ' != prev { if(prev) printf "\n";
prev=; printf "%s", ; next }
{ printf " %s", }
END { if (prev) printf "\n" }' file
要按每条记录的长度排序,你需要在阅读时记住一些东西。上面的代码因其简单性和健壮性(应该适用于任何大小的文件)而很有吸引力,但我们可以让它更复杂一点,在每行前面打印一个排序键,代价是需要将每条完整记录保存在记忆,直到我们知道它的长度。
awk 'function pr () { printf "%i\t", n; printf "%s", a[1];
for(i=2; i<=n; ++i) printf " %s", a[i];
printf "\n"; delete a; n=0 }
!= prev { if (prev) pr(); prev=; a[1]=; n=1; next }
{ a[++n] = }
END { if (n) pr() }' file |
sort -t $'\t' -k1rn |
cut -f2-