Awk добавить еще один столбец — 3-й столбец равен строке

#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  
  

Объяснение:

  1. Приведенный выше код создает 2D-массив (строка / поля)
  2. Он также хранит max_fields
  3. для каждой строки, если количество полей меньше 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, когда входной файл разделен табуляцией, заключается в том, что весь разделитель вывода строки не «пересчитывается» при замене, потому что это первый заменяемый разделитель.