我有一个.tsv
文件 ( batch_1.catalog.tags.tsv
) 包含 1,965,056 行 14 列。我想将其中一些分成两行。
第一行:以大于号 (>) 开头,后跟 14 列中的 8 列
第二行:仅第 10 列
例如。
>column3(a number) column4(numbers and letters) column5(a number) column6(- or +) column11(0 or 1) column12(0 or 1) column13(0 or 1) column14(0 or 1)
column10(string with As,Ts,Gs,Cs, and sometimes Ns)
以下是文件第六行的示例.tsv
,由第三列指定:
0 1 6 gi|586799556|ref|NW_006530744.1| 141 + consensus 0 1_33,14_43 CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC 0 0 0 0
这就是我想要的:
>6 gi|586799556|ref|NW_006530744.1| 141 + 0 0 0 0
CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC
但是,我只想对 tsv 文件 (batch_1.catalog.tags.tsv) 中第三列编号与不同文本文件 (whitelist.txt) 中的数字匹配的行执行此操作。
在上面的示例中,whitelist.txt
文件将包含数字 6,尽管还有 8000 多行具有不同的第三列数字(即 ID)。其中whitelist.txt
包括最多 6 位数字。
我一直在尝试另一种方法。我得到了下面的代码,用于使用白名单从文件中提取第 10 列.tsv
。然而,grep 持续了 10 个小时并没有做任何事情(空cat.fa
文件)。
cat whitelist.txt | while read line; do zgrep "^0 1 $line " batch_1.catalog.tags.tsv.gz; done | cut -f 3,10 | sed -E -e's/^([0-9]+) ([ACGTN]+)$/>\1Z\2/' | tr "Z" "\n" > cat.fa
下面使用 awk 或 perl 的两个解决方案都可以完美工作。尽管白名单中的 ID 不按顺序排列,但它们也会按顺序打印出来。 Perl 解决方案打印以制表符分隔的行,而 awk 则打印以空格分隔的行。
答案1
perl -F'\t+' -lane '
@ARGV and $h{$F[0]}++,next;
print ">", join("\t", @F[2..5,-4..-1]), $\, $F[9] if exists $h{$F[2]};
' whitelist.txt batch_1.catalog.tags.tsv
假设您的文件是制表符分隔的。
请注意,如果您的文件可能有 windows 或 mac 行结尾,那么谨慎的做法是首先通过实用程序 dos2unix 等将它们转换为 unix 行结尾(“\n”)。因为很多时候,我们发现提供的代码没有由于诸如此类的原因,在OP端工作。
工作原理
- 请注意何时
Perl
处理第一个参数(在本例中为 ,whitelight.txt
则 @ARGV 保存batch_1.catalog.tsv
文件,即 @ARGV = 1 => @ARGV 在布尔上下文中被评估为 TRUE。 @ARGV and $h{$F[0]}++,next
可以解释为:当我们处理白光文件时,然后将该$F[0]
文件的第一个字段( )添加到哈希中%h
,然后立即转到下一行。- 这些下面的任何行都将处理 TSV 文件,因为当时 @ARGV 不包含任何内容,因此计数为零。
- 只有那些第三个字段
$F[2]
恰好是哈希中的键的 TSV 文件记录才应转到标准输出%h
。 - 一旦决定打印 TSV 记录,则其打印格式为:(注意:
OFS
打印的默认格式为NULL
) ">"
,$F[2]
意味着第三个字段前面有一个>
- 字段 4,5,6 =>
@F[3..5]
将按 TAB 分隔和连接。 - 最后 4 个字段 =>
@F[-4..-1]
将按 TAB 分隔和连接。 - 第 10 个字段
$F[9]
前面将有一个换行符,该换行符由$\
==由于选项ORS
而提供。\n
Perl
-l
答案2
awk解决方案:
假设来自文件的测试片段batch_1.catalog.tags.tsv
:
0 1 6 gi|586799556|ref|NW_006530744.1| 141 + consensus 0 1_33,14_43 CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC 0 0 0 0
1 2 7 hi|686711556|ref|NW_006530744.2| 141 + consensus 0 1_33,14_43 CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC 1 1 0 1
2 2 8 hi|686711556|ref|NW_006530744.2| 141 + consensus 0 1_33,14_43 CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC 1 1 1 1
3 3 9 th|776711556|ref|NW_006530744.2| 141 + consensus 1 1_33,14_43 CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC 1 0 1 1
whitelight.txt
以及文件中的测试片段:
6
7
9
命令:
awk 'NR==FNR{ a[$0]++; next }{ if ($3 in a) {
$0=">"$3 FS $4 FS $5 FS $6 FS $11 FS $12 FS $13 FS $14 RS $10; print}}' whitelist.txt batch_1.catalog.tags.tsv > cat.fa
最终cat.fa
内容:
>6 gi|586799556|ref|NW_006530744.1| 141 + 0 0 0 0
CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC
>7 hi|686711556|ref|NW_006530744.2| 141 + 1 1 0 1
CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC
>9 th|776711556|ref|NW_006530744.2| 141 + 1 0 1 1
CGGGCGGTGGTGGCGCACGCCTTTAATCCCAGCACTTGGGAGGCAGAGGCAGGTGGATCTTTGTGAGTTCGAGGCCAGCCTGGGCTACCAAGTGAGCTCC
细节:
NR==FNR
- 对第一个文件执行操作,即whitelight.txt
a[$0]++;
- 从whitelight.txt
文件中累积数字
if ($3 in a)
- 如果第二个文件中的第三列值与任何累积数字匹配,则允许执行操作
RS
- awk的记录分隔符,默认为换行符