Самый простой способ извлечь часть строки?

Это, по сути, то, чтоspiffсделал, и было несколько других того же рода (, не столь хорошо известных ). spiffбыл довольно хрупким (легко сбросил керн ).

0
11.07.2019, 15:33
7 ответов

Это требует рефакторинга, но должно делать то, что вы хотите:

while IFS=; read -r line; do grep -Fw "$line" biffile.txt; done < other_file | awk -F';' '{split($3,a,"=");print a[2]}'
0
28.01.2020, 03:27

Попробуйте это,

    grep "ID=$pattern;" file | grep -o 'Name=[^;]*' | sed 's/Name=//g';
  • grep -o 'Name=[^;]*'с помощью grep шаблон начинается с "Name=" и немедленно заканчивается ";"
  • sed 's/Name=//g';просто удалите шаблон, который не требуется в соответствии с вашими требованиями.
-2
28.01.2020, 03:27

Предполагая, что это 9-я вкладка -поле с разделителями файла GFF(поле «атрибуты» ), вы можете извлечь значение атрибута gene, соответствующее конкретному IDатрибут (читается из отдельного файла )вот так сawk:

BEGIN { FS = "\t" }

FNR == NR {
    # Read IDs into a hash as keys.
    ids[$1] = 1
    next
}

$3 == "gene" {
    # Split the attribute field into separate key-value pairs.
    n = split($9, keyvalues, ";")

    id = ""    # Not found a gene ID yet
    gene = ""  # No gene name to print

    # Loop over the key-value pairs, split them on the "="
    # and extract the gene name and gene ID.
    for (i = 1; i <= n; ++i) {
        split(keyvalues[i], attr, "=")
        if (attr[1] == "ID") {
            if (attr[2] in ids)
                id = attr[2]
            else
                next  # This line is not of interest
        }
        else if (attr[1] == "gene")
            gene = attr[2]
    }

    if (id != "" && gene != "")
        print gene
}

Запуск этого в файле GFF с именем file.gff, содержащем заданные данные в столбце 9 и со списком идентификаторов генов в id.list:

.
$ awk -f script.awk id.list file.gff
LOC108565285
LOC108569527

Список идентификаторов генов считывается из первого файла в блоке FNR == NRв коде awk, тогда как последний блок обрабатывает атрибутивное поле характерных линий генов (только )во втором (и все последующие )файлы, заданные в командной строке.

Код awkпредполагает, что атрибуты IDи geneфайла GFF содержат только одно значение (без запятой -список значений с разделителями )и что значения не цитируется.

Чтобы получить вывод в виде списка имен генов и идентификаторов генов (два столбца ), измените оператор print geneна print id, gene.

2
28.01.2020, 03:27

Я бы использовал немного другой подход. Первый,извлечь только поля ID и Name:

$ sed -nE 's/.*ID=([^;]*).*Name=([^;]*).*/\1 \2/p' file1
gene27 LOC108565285
gene28 LOC108569527
gene78 LOC108562956

Затем отфильтруйте это, используя список целевых идентификаторов:

$ cat file2
gene27
gene28
$ sed -nE 's/.*ID=([^;]*).*Name=([^;]*).*/\1 \2/p' file1 | grep -wf file2 
gene27 LOC108565285
gene28 LOC108569527

Или, если вам нужно только значение LOC....и предполагается, что у вас есть GNUgrep:

$ grep -wf file2 file1 | grep -oP 'Name=\K[^;]+'
LOC108565285
LOC108569527
0
28.01.2020, 03:27

Выполняется простым скриптом ниже

команда

for i in `cat file2`; do awk -v i="$i" -F ";" '$1=="ID="i{print $5}' file1| awk -F  "=" '{print $NF}'; done

выход

LOC108565285
LOC108569527
0
28.01.2020, 03:27

Сейф. Простой. Короткий.

Название bigfile.txtпредполагает, что мы не хотим выполнять grep несколько раз, а делаем это за один проход. Поэтому я предпочитаю попытку, подобную @Kusalananda :Соберите все идентификаторы генов для извлечения, а затем просканируйте один раз через bigfile. Для такой задачи я предпочитаю sed, так как вам не нужно иметь дело с программированием, таким как переменные, массивы и циклы, просто позвольте инструменту сделать всю работу:

sed '/^gene[0-9]*$/{s/$/;/;H;d;};G;/ID=\(gene[0-9]*;\).*\n\1/!d;s/.*gene=\(LOC[0-9]*\);.*/\1/' genelist.txt bigfile.txt

А вот и объяснение:

  • /^gene[0-9]*$/— шаблон для выбора строк списка :просто geneс номером
  • {s/$/;/;H;d;}выполняется только для строк выше:s/$/;/добавляет ;, Hдобавляет эту измененную строку в область хранения и dостанавливает дальнейшую обработку и удаляет строку
  • В этот момент скрипта мы знаем, что находимся в bigfile.txtи пространство хранения заполнено всеми идентификаторами генов. Теперь Gдобавляет этот список в пространство шаблонов
  • Шаблон /ID=\(gene[0-9]*;\).*\n\1/выбирает строки, в которых ID gene[0-9]*повторяется (\1относится к строке внутри первой пары\(\))после новой строки,таким образом, идентификатор, который присутствует в списке
  • !dинвертирует выделение и удаление, чтобы все строки без совпадений удалялись
  • Теперь для всех строк с совпадением извлеките поле gene:s/.*gene=\(LOC[0-9]*\);.*/\1/
0
28.01.2020, 03:27

Попробуйте это

grep "ID=gene[0-9]" bigfile.txt |  sed 's/\;/ /g' | awk '{print $3}' | sed 's/Name=//g'
-1
25.12.2020, 16:07

Теги

Похожие вопросы