#awk #sed #vcf-vcard
#awk #sed #vcf-визитная карточка
Вопрос:
У меня есть файл VCF (с разделителями табуляции), в котором некоторые значения «RPB» пропали без вести во 2-м столбце, и это как бы сдвинуло всю строку влево.
У меня есть следующее:
1 AF1=23 AC1=23
2 RPB=123 AF1=23 AC1=23
3 AF1=23 AC1=23
Мне нужно следующее:
1 NULL AF1=23 AC1=23
2 RPB=123 AF1=23 AC1=23
3 NULL AF1=23 AC1=23
Я попробовал это, это сработало с треском..:
awk 'if($2="AF1%" {print $1,"t"NULL"t", print$2, print$3}' input.vcf > output.vcf
Я должен импортировать этот VCF в MySQL, чтобы сохранить разграничение табуляции .. есть идеи?
Комментарии:
1. Можете ли вы подтвердить, что его табуляция разделена, или это пробел?
Ответ №1:
$ awk 'NF<4{sub(/t/,"amp;NULLamp;")}1' file
1 NULL AF1=23 AC1=23
2 RPB=123 AF1=23 AC1=23
3 NULL AF1=23 AC1=23
Кстати, вы были не СЛИШКОМ далеки от функционального решения с вашей попыткой:
awk 'if($2="AF1%" {print $1,"t"NULL"t", print$2, print$3}' input.vcf
Эта минимально измененная версия привела бы к желаемому результату:
awk '{if($2~/^AF1/) print $1 "tNULLt" $2 "t" $3; else print}' input.vcf
но, как вы можете видеть, это не очень идиоматичный подход.
Комментарии:
1. Ваши ответы были бы гораздо более полезными, если бы вы действительно объяснили их, это никому не помогает, кроме OP и только для этого очень конкретного экземпляра.
2. Я не согласен, любой, кто не понимает ответа и хочет, может посмотреть руководство и попытаться разобраться в нем, а затем, если они не могут понять это сами, они могут задавать вопросы. Гораздо полезнее для процесса обучения, чем кормление с ложки.
3. Ваш ответ — это само определение кормления с ложечки, вы буквально только что дали им ответ, при этом они вообще не выполняли никакой работы.
4. Как бы я, предоставив объяснение в дополнение к ответу, как вы предложили в своем первом комментарии, потребовал дополнительной работы с их стороны? Вы говорите по кругу. Давайте просто согласимся не согласиться.
5. Спасибо, никогда не знал фактической причины, когда использовать
"
в контексте RE.
Ответ №2:
этот однострочный awk поможет вам:
kent$ awk -F't' -v OFS='t' '!($2~/^RPB=/){$2="NULLt"$2}7' file
1 NULL AF1=23 AC1=23
2 RPB=123 AF1=23 AC1=23
3 NULL AF1=23 AC1=23
Комментарии:
1. Это некорректно работает с указанными данными, поскольку они разделены пробелом, а не разделены табуляцией. Из теста OPs кажется, что он разделен табуляцией, поэтому я изменил исходное сообщение на вкладку. Некоторые игры в гольф:
awk -F't' -v OFS='t' '$2!~/^RPB=/{$2="NULL"FS$2}7'
Ответ №3:
ИМХО, вам не следует использовать регулярные выражения, попробуйте это:
#!/bin/bash
cat input.vcf |
perl -ane '
BEGIN{$c=0;$max_fields=0}
$c2=0;
foreach(@F){
$a[$c][$c2]=$_;
if( $c2 > $max_fields ) {
$max_fields=$c2;
}
$c2
}
$c ;
END{
foreach $i (@a){
while (@$i < $max_fields 1 ){
unshift (@$i,"NULL");
}
}
foreach $i (@a){
foreach $x (@$i){
print $x,"t";
}
print "n";
}
}'
Вывод:
bash test.sh
NULL AF1=23 AC1=23
RPB=123 AF1=23 AC1=23
NULL AF1=23 AC1=23
Объяснение:
- Приведенный выше код создает 2D-массив (строка / поля)
- Он также хранит max_fields
- для каждой строки, если количество полей меньше max_fields, чем вставить «NULL» в начало строки
Ответ №4:
На основе входного файла с разделителями табуляции:
awk -v OFS="t" 'NF==3{$1=$1 OFS "NULL"} 1' input.vcf
где это может быть изменено на следующее, если входной файл не разделен табуляцией:
awk -v OFS="t" '{$1=$1 (NF==3 ? OFS "NULL" : "")} 1' input.vcf
В любом случае, когда NF==3
первое поле переназначается, чтобы содержать недостающие данные. В первом примере требуется настройка только выходных разделителей измененных строк, но когда данные не разделены табуляцией, каждая строка должна быть «пересчитана» с повторным назначением до того 1
, как будет напечатана вся строка.
Прелесть ответа Ed, когда входной файл разделен табуляцией, заключается в том, что весь разделитель вывода строки не «пересчитывается» при замене, потому что это первый заменяемый разделитель.