打印符合条件的 header 下面的行

Print lines below a header matching a condition

我有这样一个数据库:

>2654570298
MRNYSYKGKWEKLLTPEIVKKLTLINEFKGEQRLFIKAHKDELKELSELA
KIQSTEASNKIEGIFTSDDRFKSLAQAKTTPRNRNESEIAGYRDVLNTIH
DSYEYIPISASYFLQLHRDLYKFVAKNDVGKFKSSDNIIRETDEKGNERL
RFRPVPAWETPAAIDELCKAYADAKEEIDPLILNAMFILDFLCIHPFNDG
NGRMSRLLTLLLLYKTGFIVGKYISIEKIIEESKETYYEVLQDSLVGWHE
NENDYKPFVNYMLGVIVNAYKEFESRTELVTNPNLTKSDRIREIIKDHIG
TITKAELLEMNPDISDTTVQRTLAKLLKNNDIKKIGGGRYTKYTWNTEEQ

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570301
MNESELYKELGILTKDKSKWAENIQYVSSLLNHESAKIQAKALWLLGEMG
LEYPDSIQDAVPMVASFCDSENALLRERAVNALGRIGRGNYNLIEPYWSD
LFRFASDDEPKVRLSFIWASENVATNTPDIYENHMSVFESLLHDIDDKVR
MESPEIFRVLGKRRPEFVIPYIEQLQKMAETDSNRVVRIHSLGAIKVTTS
K

>2654570302
MWNMIWPLVLIVGSNCFYNICTKSMPEGTNTFGALTVTYLVGAVLSAVLF
VVSVKPAGVLNEISKINWTSFVLGLVIVGLEAGYVFLYRAGWKVSNGALT
ANICLAIALIVIGFLLYKESISIKQVAGIVVCGFGLFLING

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

我想过滤它只打印 header 包含“|K”的序列,使用 awk、grep 或类似的东西。期望的输出:

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

请注意,一个 header 和下一个 header 之间的行数并不总是相同的,并且换行符始终将一个序列与随后的 header.

分开

有人可以帮忙吗?

使用 awk 或 sed:

sed -e '/|K/, /^$/ p; d' database.txt
awk '/\|K/, /^$/' database.txt

这两个都做完全相同的事情——它们检查一行中的 |K 并打印直到它们看到下一个空白行。在 sed 语法中,打印是显式的 p(后面的 d 清除缓冲区以移动到下一个输入行),而 awk 示例利用更隐式的 awk“默认操作”行为。

这两个工具在匹配语法中使用的正则表达式语言版本之间存在一些差异 -- 因为`|`字符可以具有特殊含义,因此必须在例子。

为了更好地理解语法,awk 和 sed 都记录在它们的 "man pages" 中——请参阅此文档以了解有关这些语言如何工作的更多信息。

如果取消设置记录分隔符 (RS),awk 会将每个部分视为 一条记录,例如查找其中包含 |K 的记录:

awk '/\|K/' RS=

输出:

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI
>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

现在,如果您希望输出是双重 new-line 分隔且仅匹配 header,您可以更改字段分隔符 (FS) 和输出记录分隔符 (ORS), 例如:

awk ' ~ /\|K/' RS= FS='\n' ORS='\n\n'

输出:

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

我会按照以下方式使用 GNU AWK 完成此任务,令 file.txt 内容为

>2654570298
MRNYSYKGKWEKLLTPEIVKKLTLINEFKGEQRLFIKAHKDELKELSELA
KIQSTEASNKIEGIFTSDDRFKSLAQAKTTPRNRNESEIAGYRDVLNTIH
DSYEYIPISASYFLQLHRDLYKFVAKNDVGKFKSSDNIIRETDEKGNERL
RFRPVPAWETPAAIDELCKAYADAKEEIDPLILNAMFILDFLCIHPFNDG
NGRMSRLLTLLLLYKTGFIVGKYISIEKIIEESKETYYEVLQDSLVGWHE
NENDYKPFVNYMLGVIVNAYKEFESRTELVTNPNLTKSDRIREIIKDHIG
TITKAELLEMNPDISDTTVQRTLAKLLKNNDIKKIGGGRYTKYTWNTEEQ

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570301
MNESELYKELGILTKDKSKWAENIQYVSSLLNHESAKIQAKALWLLGEMG
LEYPDSIQDAVPMVASFCDSENALLRERAVNALGRIGRGNYNLIEPYWSD
LFRFASDDEPKVRLSFIWASENVATNTPDIYENHMSVFESLLHDIDDKVR
MESPEIFRVLGKRRPEFVIPYIEQLQKMAETDSNRVVRIHSLGAIKVTTS
K

>2654570302
MWNMIWPLVLIVGSNCFYNICTKSMPEGTNTFGALTVTYLVGAVLSAVLF
VVSVKPAGVLNEISKINWTSFVLGLVIVGLEAGYVFLYRAGWKVSNGALT
ANICLAIALIVIGFLLYKESISIKQVAGIVVCGFGLFLING

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

然后

awk 'BEGIN{RS=ORS="\n\n"}index([=11=],"|K"){print}' file.txt

输出

>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED

说明:我将行分隔符和输出行分隔符设置为双换行符,换句话说就是空白行,所以每个部分都被视为单行。然后我使用 index function to check if section contain |K. This function does return 0 if no match, position of match if found. print is done only in latter case. Note that this function accept string ("|K") rather than pattern (/\|K/), so I do not have to care about characters with special meaning like |. If you want to know more about RS, ORS or other built-in AWK variables read 8 Powerful Awk Built-in Variables – FS, OFS, RS, ORS, NR, NF, FILENAME, FNR

(在 gawk 4.2.1 中测试)

同时使用 awk 这可以帮助您:

awk '/^>/ {f=/\|K/} f' file
>2654570299|K03427
MITGELKNKIDGLWDVFAAGGLVNPLEVIEQITYLMFIKDLDDVDKRKEK
ESAMLGLPYKSIFAGEVKIGDRTIEGTQLKWSVFHDFSAGRMYAIMQEWV
FPFIKNLHSDKNSTYSKYMDDAIFKFPTPLLLSKVVDSLDEIYEIMNSTL
VLDVRGDVYEYLLNKIASAGRNGQFRTPRHIIRMMVEMVEPKADDVICDP
GDLLKVCKTKKTELLFLALFLRMLKVGGRCACIVPDGVLFGSSKAHKDIR
KQVVEENRLEAVISMPSGVFKPYAGVSTAILIFTKTGHGGTDNVWFYDMT
ADGYSLDDKRTPVSENDIPDIIERFKNLDKEIDRERTDKSFMVPKQDIAD
NDYDLSINKYKEVVYEKIEYPPTSEIMADIREIEMEIGKEMDELEKLLNI

>2654570303|K01153
MKNKELLKRVGYVVLICLSFFVATWYFFENNKICTICWIAIGSKNVYDLV
HRIKNSKKED
  • 如果 f 为真,打印这些行。默认情况下,在awk条件判断为真时,打印$0的内容。
  • 您可以看到 f 的值带有 print
  • 哪些行或记录为真:
awk '/^>/ {f=/\|K/} f {print NR, f}' file