命令行:使用 grep 仅获取部分行

命令行:使用 grep 仅获取部分行

我有一个包含如下行的文件:

1   train   tree    11869   12227   .   +   .   leaf_id "ENSG00000223972"; root_id "ENST00000456328";

我正在搜索的行必须train位于第二列和tree第三列中。

我只想获取引号内的leaf_id以 开头的内容。行的其余部分不相关。我已经尝试使用正则表达式和捕获组进行 grep,但没有成功...ABC

列之间用 分隔\t,而不是空格。请注意,最后一个字段是leaf_id "ENSG00000223972"; root_id "ENST00000456328";,其中的条目之间用空格分隔,而不是制表符。

谢谢

答案1

实际上,您可以使用 GNU 执行此操作grep,只要字符串treetrain分别出现在第二个和第三个字段上,而不是其他任何地方:

$ grep -oP 'train\ttree\t.*leaf_id "\K[^"]+' file
ENSG00000223972

make-ogrep打印该行的匹配部分,并且-P启用 Perl 兼容的正则表达式,为我们提供+\K

正则表达式将搜索train,然后是 a \t,然后\tree是 another \t,然后是任何内容,直到找到为止leaf_id "。然后,\K告诉grep我们忘记到目前为止匹配的一切。因此,我们现在寻找"此后最长的非字符段,这将是您要查找的基因名称。


要仅匹配treetrain位于正确的列中,您可以执行以下操作:

$ awk -F'\t' '$2=="train" && $3=="tree"' file | grep -oP 'leaf_id "\K[^"]+'
ENSG00000223972

或者:

$ perl -F'\t' -lane 'if($F[1] eq "train" && $F[2] eq "tree" && $F[8]=~/leaf_id\s+"\K([^"]+)/){print $1}' file
ENSG00000223972

答案2

您可以用于awk此任务。假设您的文件被称为input.tsv,相关命令将是:

awk -F"\t" '$2=="train" && $3=="tree" {split($9,f,"\""); print f[2]}' input.tsv

这会将每个 TAB ( -F"\t") 处的行拆分为单独的字段。如果第二个字段是train且第三个字段是tree,则检查第 9 个字段并打印双引号内的字符串。

后者是通过(错误)使用以下split()命令来实现的:该字段在每个双引号处拆分,并将所有部分保存在数组变量中f。第二个条目f[2]awk数组通常从 1) 开始是引号内的字符串并被打印(第一个条目fleaf_id,第三个条目是; root_id等等)。

答案3

使用 sed :

$ sed -nE 's/^.*train.*tree.*leaf_id "([A-Z][A-Z0-9]*)";.*$/\1/p' file
ENSG00000223972

相关内容