
У меня есть такой файл:
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)