根據特定列將一行解構為兩行
我有一個包含1,965,056 行 14 列
.tsv
的文件 (batch_1.catalog.tags.tsv
) 。我想把其中的一些分成兩行。第一行:以大於號 (>) 開頭,後跟 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 位數字。我一直在嘗試另一種方法。我得到了下面的程式碼,用於使用白名單從
.tsv
文件中提取第 10 列。但是,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 列印以空格分隔的行。
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 的記錄分隔符,預設為換行符
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
假設您的文件是 TAB 分隔的。
請注意,如果您的文件可能有 windows 或 mac 行尾,那麼謹慎的做法是首先通過實用程序 dos2unix 等將它們轉換為 unix 行尾(“\n”)。因為很多時候看到提供的程式碼沒有由於這些原因,在 OP 的最後工作。
工作
- 注意何時
Perl
處理第一個參數(在這種情況下, @whitelight.txt
ARGV 保存batch_1.catalog.tsv
文件,即@ARGV = 1 => @ARGV 在布爾上下文中被評估為 TRUE。@ARGV and $h{$F[0]}++,next
應該解釋為:當我們在處理whitelight文件時,然後,將該文件的第一個欄位($F[0]
)添加到雜湊中,%h
然後立即進入下一行。- 這些下面的任何行都將處理 TSV 文件,因為當時 @ARGV 沒有任何內容,因此計數為零。
- 只有那些 TSV 文件記錄才能轉到標準輸出,其第三個欄位
$F[2]
恰好是%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
。