Сопоставление 2 основных столбцов между файлами; и вставка других столбцов в выходной файл, когда эти основные столбцы совпадают. Сохранять размер строки в 1-м файле

Date не принимает этот формат ввода, попробуйте поставить год первым, например, stream Редактирование ввода:

cut -f 9 file | sed 's/\(..\)-\(..\)-\(....\)/\3-\1-\2/' > tmpfile

Проверка вручную:

$ date --date '09-13-1970' "+%B %d, %Y"
date: invalid date ‘09-13-1970’

$ date --date '09/13/1970' "+%B %d, %Y"
September 13, 1970

$ date --date '1970/09/13' "+%B %d, %Y"
September 13, 1970

$ date --date '1970-09-13' "+%B %d, %Y"
September 13, 1970
1
13.04.2017, 15:36
1 ответ

Создайте следующие файлы:

merge21 :

BEGIN {
        FS = "\t"
        OFS = "\t"
}
NR==FNR {               # file2
        key = $2 "," $3
        present[key] = 1
        minor8[key] = $1
        next
}
{                       # file1
        key = $1 "," $3
        if (present[key]) print $1, $2, $3, $4, minor8[key]
        else              print $1, $2, $3, $4, "-"
}

merge312 :

BEGIN {
        FS = "\t"
        OFS = "\t"
}
NR==FNR {               # file3
        key = $1 "," $2
        present[key] = 1
        minor9[key] = $3
        next
}
{                       # file1 + file2
        key = $1 "," $3
        if (present[key]) print $1, $2, $3, $4, $5, minor9[key]
        else              print $1, $2, $3, $4, $5, "-"
}

Они почти идентичны; Я выделил различия жирным шрифтом. Теперь введите команду

awk -f merge21 file2 file1 | awk -f merge312 file3 -

. Предполагается, что ни одно из ваших ключевых полей не содержит запятых и ни в одном из ваших данных нет дефисов, , но на самом деле это зависит только от них некоторые строки , которые не отображаются в данных. Было бы тривиально расширить это для поддержки большего количества столбцов; Я надеюсь, что это очевидно. Этот может быть расширен, чтобы делать все за один прогон awk , но это было бы немного сложнее, и (IMNSHO) не стоит усилие.

Это создает так называемое «левое внешнее соединение» данных в ваших файлах; см. Различие между INNER и OUTER соединениями в Stack Overflow для некоторых определений .(«Левое внешнее соединение» определяется в принятом ответе на этот вопрос как (перефразировано) «все строки в первой таблице плюс любые общие строки в другой таблице (ах)». )

Ваш вывод будет

MAIN1   minor1  MAIN2   minor3  minor8  minor9
1       bla1    a       blabla1 yes6    sure3
1       bla2    b       blabla2 yes7    sure4
1       bla3    c       blabla3 yes8    sure5
2       bla4    a       blabla4 yes9    sure6
2       bla5    d       blabla5 -       sure7
3       bla6    e       blabla6 yes2    sure8
4       bla7    f       blabla7 yes3    sure9
5       bla8    a       blabla8 yes4    -
5       bla9    g       blabla9 yes5    sure2

и, очевидно, вы можете удалить символы - с помощью sed . (И, конечно, если ваши реальные данные действительно содержат дефисы, выберите какой-нибудь неиспользуемый символ или строку в качестве заполнителя для отсутствующих данных.)


Примечания

  • FS и OFS являются разделителем входного поля и разделителем выходного поля соответственно. (Очевидно IFS бессмысленен в awk ; это была ошибка с моей стороны.) Вам, вероятно, действительно не нужен FS = "\ t" - awk по умолчанию распознает табуляции как разделители полей при вводе. (Он позволяет вам иметь поля, содержащие пробелы, , но, похоже, вас это не интересует.) OFS = "\ t" является важным; из-за этого я могу сказать напечатать $ 1, $ 2, $ 3, $ 4 и получить поля ввода output с табуляцией между ними. Если бы я не сказал OFS = "\ t" , они были бы разделены пробелами, если я не сказал print $ 1 "\ t" $ 2 " \ t "$ 3" \ t "$ 4 , , что утомительно и ухудшает удобочитаемость.
  • Если вы задали дополнительные ограничения для MAIN1 и MAIN2 - например, , они всегда состоят из одного символа каждый, или MAIN1 всегда является числом, а MAIN2 всегда начинается с буквы - { {1}} Мне не нужна была бы запятая (, ) в ключе . Но в исходной версии вашего первого вопроса такого ограничения нет. Рассмотрим следующие данные:

     MAIN1 ($ 2) MAIN2 ($ 3) badkey = $ 2 $ 3 goodkey = $ 2 "," $ 3 
    2 34151 234151 2,34151 
    23 4151 234151 23,4151 
     

    Если мы не добавим в ключ какой-либо символ-разделитель, который иначе не появится в ключевых полях (MAIN1 и MAIN2), мы можем получить одинаковое значение ключа для разных строк.

  • Рискуя расколоться, я ничего не «говорю Linux»;Я говорю awk , что делать.
  • По поводу кода
     NR == FNR {# file3 
    key = $ 1 "," $ 2 
    present [key] = 1 { {1}} minor9 [key] = $ 3 
    next 
    } 
    Рассмотрим седьмую с последней строки file3 , который содержит 1 a sure3 . Очевидно, у нас есть $ 1 = 1 , $ 2 = a и $ 3 = sure3 , поэтому ключ = 1, a . present [key] = 1 означает, что я устанавливаю present ["1, a"] на 1 как флаг {{1} }, чтобы указать, что file3 имеет a 1, строку ; т. е. что существует значение minor9 для ключ = 1, a . Поскольку нет 5, строка в file3 , present ["5, a"] не устанавливается, {{ 1}} и поэтому часть кода " file1 + file2 " знает, что нет minor9 для ключа = 5, a , , и вместо этого он должен вывести - . Имя присутствует - это просто произвольный выбор с моей стороны; оно означает, что строка 1, присутствует в file3 (а в 5, в строке нет). Обычно используется 1 для представления «ИСТИНА».
  • Вы можете заменить print $ 1, $ 2, $ 3, $ 4 на for (n = 1; n <= 4; n ++) printf "% s \ t", $ n . Вы должны завершить строку, используя простой print (в отличие от printf ) для последнего поля, либо выполнив printf "\ п" . Вы можете упростить еще больше, выполнив что-то вроде

      for (n = 1; n <= 4; n ++) printf "% s \ t", $ n 
    if (present [key ]) print minor8 [key] 
    else print "-" 

Прочтите awk (1) , спецификацию POSIX для awk , {{ 1}} Руководство пользователя GNU Awk и дополнительную информацию см. В Awk.info .

2
27.01.2020, 23:36

Теги

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