根据相似部分合并两个文件中未排序的行
Merge unsorted lines from two files based on similar part
我想知道是否可以基于相似部分将两个文件中的信息合并在一起。 file1是blast后的序列ID,file2是序列名前两个数字对应的分类名。
文件 1:
>301-89_IDNAGNDJ_171582
>301-88_ALPEKDJF_119660
>301-88_ALPEKDJF_112039
...
文件 2:
301-89--sample1
301-88--sample2
...
输出:
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_119660--sample2
>301-88_ALPEKDJF_112039--sample2
文件未排序,文件 1 包含更多行,其中前两个数字与文件 2 中一行中的前两个数字相似。我正在寻找一些关于如何做到这一点的 tips/help,可以这样做吗?我应该使用哪种命令或语言?
使用awk
$ awk -F"[_-]" 'BEGIN{OFS="-"}NR==FNR{a[]=;next}{print [=10=],a[]}' file2 OFS="--" file1
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_119660--sample2
>301-88_ALPEKDJF_112039--sample2
I am wondering if is it possible to merge information from two files together based on a similar part
是的...
The files are unsorted
...但前提是它们已排序。
如果我们转换它们使分隔符保持一致,然后稍后再将其重新格式化,会更容易:
sed 's/>\([0-9]*-[0-9]*\)_\(.*\)$/ /' file1
产生
301-88 ALPEKDJF_112039
301-88 ALPEKDJF_119660
301-89 IDNAGNDJ_171582
...
我们可以直接通过管道 sort -k1
sed 's/--/ /' f2
产生
301-89 sample1
301-88 sample2
...
我们可以用同样的方式排序
join sorted1 sorted2
(加上前面步骤的排序结果)产生
301-88 ALPEKDJF_112039 sample2
301-88 ALPEKDJF_119660 sample2
301-89 IDNAGNDJ_171582 sample1
...
最后我们可以通过管道
按照您最初的要求格式化这 3 个字段
sed 's/\(.*\) \(.*\) \(.*\)$/_--/'
如果动态对它们进行排序是合理的,我们可以使用进程替换来做到这一点:
$ join \
<( sed 's/>\([0-9]*-[0-9]*\)_\(.*\)$/ /' f1 | sort -k1 ) \
<( sed 's/--/ /' f2 | sort -k1 ) \
| sed 's/\(.*\) \(.*\) \(.*\)$/_--/'
301-88_ALPEKDJF_112039--sample2
301-88_ALPEKDJF_119660--sample2
301-89_IDNAGNDJ_171582--sample1
...
如果对文件进行排序是不合理的——即时或以其他方式——你将最终在内存中构建一个散列,就像 awk
答案所做的那样。试试看哪个更快。
(mawk/nawk/gawk -e/-ce/-Pe) '
FNR == !_ {
_ = ! ( ___=match(FS=FNR==NR ? "[-][-]" : "[>_]", "[>-]"))
$_ = $_
} FNR == NR { __[$!_]="--"$NF; next } sub("$", __[$___])' file2.txt file1.txt
————————————————————————————
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_112039--sample2
>301-88_ALPEKDJF_119660--sample2
我想知道是否可以基于相似部分将两个文件中的信息合并在一起。 file1是blast后的序列ID,file2是序列名前两个数字对应的分类名。
文件 1:
>301-89_IDNAGNDJ_171582
>301-88_ALPEKDJF_119660
>301-88_ALPEKDJF_112039
...
文件 2:
301-89--sample1
301-88--sample2
...
输出:
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_119660--sample2
>301-88_ALPEKDJF_112039--sample2
文件未排序,文件 1 包含更多行,其中前两个数字与文件 2 中一行中的前两个数字相似。我正在寻找一些关于如何做到这一点的 tips/help,可以这样做吗?我应该使用哪种命令或语言?
使用awk
$ awk -F"[_-]" 'BEGIN{OFS="-"}NR==FNR{a[]=;next}{print [=10=],a[]}' file2 OFS="--" file1
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_119660--sample2
>301-88_ALPEKDJF_112039--sample2
I am wondering if is it possible to merge information from two files together based on a similar part
是的...
The files are unsorted
...但前提是它们已排序。
如果我们转换它们使分隔符保持一致,然后稍后再将其重新格式化,会更容易:
sed 's/>\([0-9]*-[0-9]*\)_\(.*\)$/ /' file1
产生301-88 ALPEKDJF_112039 301-88 ALPEKDJF_119660 301-89 IDNAGNDJ_171582 ...
我们可以直接通过管道
sort -k1
sed 's/--/ /' f2
产生301-89 sample1 301-88 sample2 ...
我们可以用同样的方式排序
join sorted1 sorted2
(加上前面步骤的排序结果)产生301-88 ALPEKDJF_112039 sample2 301-88 ALPEKDJF_119660 sample2 301-89 IDNAGNDJ_171582 sample1 ...
最后我们可以通过管道
按照您最初的要求格式化这 3 个字段sed 's/\(.*\) \(.*\) \(.*\)$/_--/'
如果动态对它们进行排序是合理的,我们可以使用进程替换来做到这一点:
$ join \
<( sed 's/>\([0-9]*-[0-9]*\)_\(.*\)$/ /' f1 | sort -k1 ) \
<( sed 's/--/ /' f2 | sort -k1 ) \
| sed 's/\(.*\) \(.*\) \(.*\)$/_--/'
301-88_ALPEKDJF_112039--sample2
301-88_ALPEKDJF_119660--sample2
301-89_IDNAGNDJ_171582--sample1
...
如果对文件进行排序是不合理的——即时或以其他方式——你将最终在内存中构建一个散列,就像 awk
答案所做的那样。试试看哪个更快。
(mawk/nawk/gawk -e/-ce/-Pe) '
FNR == !_ {
_ = ! ( ___=match(FS=FNR==NR ? "[-][-]" : "[>_]", "[>-]"))
$_ = $_
} FNR == NR { __[$!_]="--"$NF; next } sub("$", __[$___])' file2.txt file1.txt
————————————————————————————
>301-89_IDNAGNDJ_171582--sample1
>301-88_ALPEKDJF_112039--sample2
>301-88_ALPEKDJF_119660--sample2