сохранить только определенную часть строки в определенном столбце

сохранить только определенную часть строки в определенном столбце

У меня есть такой файл:

id  target_id                               length  eff_length
1   intron_FBgn0000721:20_FBgn0000721:18    1136    243.944268
1   intron_FBgn0000721:19_FBgn0000721:18    1122    240.237419
2   intron_FBgn0264373:2_FBgn0264373:3      56      0
3   intron_FBgn0027570:4_FBgn0027570:3      54      0

Для 2-го столбца target_idя хочу сохранить только строку (не всегда FBgnXXXX, иногда другие имена) между intron_и первым :. Таким образом, новый выходной файл будет иметь более простое значение для столбца 2, но остальная часть файла останется прежней.

Я попробовал использовать команду sed, но не знаю, как удалить ненужную часть.

решение1

Используя sedи column:

$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/' file | column -t
id  target_id    length  eff_length
1   FBgn0000721  1136    243.944268
1   FBgn0000721  1122    240.237419
2   FBgn0264373  56      0

Ключевой частью этого является команда замены:

s/ intron_([^:]*):\S*/ \1/

Он ищет intron_и сохраняет все после intron_и до первого двоеточия в переменную 1. [^[:space:]]*соответствует всему от этого двоеточия до конца поля. Все это заменяется текстом, сохраненным в переменной 1.

Использование awkс выводом, разделенным табуляцией:

$ awk -v "OFS=\t" '{$2=$2;sub(/intron_/, "", $2); sub(/:.*/, "", $2); print}' file
id      target_id       length  eff_length
1       FBgn0000721     1136    243.944268
1       FBgn0000721     1122    240.237419
2       FBgn0264373     56      0

Объяснение:

  • -v "OFS=\t"

    Это устанавливает разделитель выходных полей на табуляцию. Это помогает выровнять столбцы, возможно, делая columnненужными.

  • $2=$2

    При печати строки awkне изменится на наш новый указанный разделитель выходных полей, если мы не изменим что-то в строке. Назначение второго поля второму полю достаточно, чтобы гарантировать, что вывод будет иметь табуляции.

  • sub(/intron_/, "", $2)

    Это удаляет intron_из второго поля.

  • sub(/:.*/, "", $2)

    Это удалит все после первого двоеточия из второго поля.

  • print

    Это напечатает нашу новую строку.

Использование awkс пользовательским форматированием столбцов

Это похоже на предыдущий пример, но позволяет printfнам настраивать ширину столбцов и выравнивание по желанию:

$ awk  '{sub(/intron_/, "", $2); sub(/:.*/, "", $2); printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4}' file
id  target_id      length eff_length
1   FBgn0000721      1136 243.944268
1   FBgn0000721      1122 240.237419
2   FBgn0264373        56   0

Здесь оператор printf "%-3s %-12s %8s %3s\n",$1,$2,$3,$4выбирает ширину столбцов и выравнивание в обычном printfстиле.

Использование sedи преобразование из табуляции в запятую

$ sed -E 's/ intron_([^:]*):[^[:space:]]*/ \1/; s/[[:space:]][[:space:]]*/,/g' file 
id,target_id,length,eff_length
1,FBgn0000721,1136,243.944268
1,FBgn0000721,1122,240.237419
2,FBgn0264373,56,0

решение2

Вы можете использовать perl:

$ perl -anle '
    BEGIN {$" = "\t"}
    print "@{[@F]}" and next if $. == 1;
    $F[1] = $1 if /_([^:]*):/;
    print "@{[@F]}";
' file
id  target_id   length  eff_length
1   FBgn0000721 1136    243.944268
1   FBgn0000721 1122    240.237419
2   FBgn0264373 56      0
3   FBgn0027570 54      0

Объяснение

  • -a: автоматическое разбиение каждой строки на массив @F.

  • BEGIN {$" = "\t"}: мы устанавливаем разделитель списка на табуляцию \t, она используется, когда массив или фрагмент массива интерполируется в строку, заключенную в двойные кавычки.

  • print "@{[@F]}" and next if $. == 1: Печатаем заголовок, переходим к следующей строке.

  • $F[1] = $1 if /_([^:]*):/: мы получаем значение между _и первым :, сохраняем его во втором элементе в @F.

  • print "@{[@F]}": просто распечатайте желаемый результат.

решение3

sed -e 'h;s/.*intron_[^:]*\(:[^[:space:]]*\).*/\1/;s/./ /g;;G;;s/\(.*\)\n\(.*\)intron_\([^:]*\):[^[:space:]]*/\2\3\1/' YourFile

В 1 sed (без конвейера) сохраняя столбец. Он использует буфер хранения

Версия Posix (также --posixв GNU sed)

Связанный контент