我有一个包含如下行的文件:
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
,只要字符串tree
和train
分别出现在第二个和第三个字段上,而不是其他任何地方:
$ grep -oP 'train\ttree\t.*leaf_id "\K[^"]+' file
ENSG00000223972
make-o
只grep
打印该行的匹配部分,并且-P
启用 Perl 兼容的正则表达式,为我们提供+
和\K
。
正则表达式将搜索train
,然后是 a \t
,然后\tree
是 another \t
,然后是任何内容,直到找到为止leaf_id "
。然后,\K
告诉grep
我们忘记到目前为止匹配的一切。因此,我们现在寻找"
此后最长的非字符段,这将是您要查找的基因名称。
要仅匹配tree
和train
位于正确的列中,您可以执行以下操作:
$ 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) 开始是引号内的字符串并被打印(第一个条目f
是leaf_id
,第三个条目是; root_id
等等)。
答案3
使用 sed :
$ sed -nE 's/^.*train.*tree.*leaf_id "([A-Z][A-Z0-9]*)";.*$/\1/p' file
ENSG00000223972