Использование sed, который понимает -E
, для использования ERE (например, GNU sed или OSX / BSD sed):
$ sed -E 's/[^=]*=([^;]*)(;[^;]*){2}[^=]*=/\1\t/' file
4 protein_coding
5 lncRNA
6 protein_coding;partial=true;start_range=.,338076
7 pseudogene;pseudo=true
С любым POSIX sed:
$ sed 's/[^=]*=\([^;]*\)\(;[^;]*\)\{2\}[^=]*=/\1\t/' file
4 protein_coding
5 lncRNA
6 protein_coding;partial=true;start_range=.,338076
7 pseudogene;pseudo=true
Кроме того, вот подход к общей работе с типом данных tag = value, который у вас будет в будущем, и который заключается в том, чтобы сначала создать массив (f[]
ниже), который сопоставляет каждый тег / имя с соответствующим значением, а затем вы можете просто доступ к значениям по их именам для сравнения, печати и т. д. c.:
$ cat tst.awk
BEGIN { FS=";"; OFS="\t" }
{
delete f
for (i=1; i<=NF; i++) {
tag = val = $i
sub(/=.*/,"",tag)
sub(/[^=]+=/,"",val)
f[tag] = val
}
<< do something with "f[tag]"s >>
}
, с помощью которого вы можете решить свою текущую проблему, используя:
$ cat tst.awk
BEGIN { FS=";"; OFS="\t" }
{
delete f
for (i=1; i<=NF; i++) {
tag = val = $i
sub(/=.*/,"",tag)
sub(/[^=]+=/,"",val)
f[tag] = val
}
sub(/.*;gene_biotype=/,"")
print f["ID"], $0
}
$ awk -f tst.awk file
4 protein_coding
5 lncRNA
6 protein_coding;partial=true;start_range=.,338076
7 pseudogene;pseudo=true
, но вы также можете сделать гораздо больше, включая печать строк на основе составных условий различных значений, печать столбцов в другом порядке, чем они были введены, и т. д. c. Например:
$ cat tst.awk
BEGIN { FS=";"; OFS="\t" }
{
delete f
for (i=1; i<=NF; i++) {
tag = val = $i
sub(/=.*/,"",tag)
sub(/[^=]+=/,"",val)
f[tag] = val
}
}
( (f["Dbxref"] > 800) && (f["partial"] == "true") ) || (f["gene_biotype"] == "protein_coding") {
print f["Name"], f["ID"]
}
.
$ awk -f tst.awk file
LOC2 4
LOC4 6