Извлечь последнюю часть строки, когда разделитель не всегда одинаков, используя awk - PullRequest
0 голосов
/ 02 апреля 2020

У меня есть файл со строками, которые выглядят так. FILE здесь

ID=4;Dbxref=766;Name=LOC2;gene_biotype=protein_coding
ID=5;Dbxref=800;Name=LOC3;gene_biotype=lncRNA
ID=6;Dbxref=900;Name=LOC4;gene_biotype=protein_coding;partial=true;start_range=.,338076
ID=7;Dbxref=905;Name=LOC5;gene_biotype=pseudogene;pseudo=true

Я пытаюсь взять последнюю часть строки ... но окончание не всегда соответствует

Я пытался :

while read -r line ; do
        ID=`echo $line | awk -F"ID=" '{print $2}' | awk -F";" '{print $1}'`
        Biotype=`echo $line | awk -F"gene_biotype=" '{print $2}'`
        echo -e $ID"\t"$Biotype >> file.txt

done << (grep $'\tgene\t' originalfile.txt)

Биотип - это часть, которая не работает. В идеале вывод будет выглядеть так:

4 protein_coding
5 lncRNA
6 protein_coding;partial=true;start_range=.,338076
7 pseudogene;pseudo=true

Я также пробовал:

    Biotype=`echo $line | awk -F"gene_biotype=" '{print $NF}'`

Но в итоге ничего не сохраняется. Любой совет приветствуется ...

1 Ответ

3 голосов
/ 02 апреля 2020

Использование 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...