LINUX.ORG.RU

bash: joun two files

 , ,


0

1

file1:

ivan  ivan1
ivan  ivan2
ivan  ivan3
petr  petr1
petr  petr2
vlad  vlad1
file2:
ivan  1
petr  2
vlad  3
нужно получить файл вида
ivan  ivan1
ivan  ivan2
ivan(1)  ivan3
petr  petr1
petr(2)  petr2
vlad(3)  vlad1
или
ivan  ivan1
ivan  ivan2
ivan  ivan3  1
petr  petr1
petr  petr2  2
vlad  vlad1  3
или в любом другом виде передать уникальное значение для каждого имени из второго файла в первый файл, где количество строк с одинаковым именем может быть разным

★★

Ответ на: комментарий от ggrn
$ sudo join file1 file2
ivan ivan1 1
ivan ivan2 1
ivan ivan3 1
petr petr1 2
petr petr2 2
vlad vlad1 3

почти, но не совсем то что хотелось бы.

nerve ★★
() автор топика
$ cat join.awk 
#!/usr/bin/awk -f

function print_prev(cur1) {
    if (cur1 != prev1)
        prev0 = prev1 "(" dict[prev1] ")" substr(prev0, length(prev1) + 1)
    print prev0
}

!dictdone && !dictfile { dictfile = FILENAME }
FILENAME != dictfile { dictdone = 1 }
!dictdone { dict[$1] = $2; next }

FNR != 1 { print_prev($1) }
{ prev0 = $0; prev1 = $1 }
END { print_prev(prev1 " ") }
$ ./join.awk file2 file1 
ivan  ivan1
ivan  ivan2
ivan(1)  ivan3
petr  petr1
petr(2)  petr2
vlad(3)  vlad1
unterwulf
()
Ответ на: комментарий от zolden
$ comm -3 file1 file2
ivan  1
ivan  ivan1
ivan  ivan2
ivan  ivan3
petr  2
petr  petr1
petr  petr2
vlad  3
vlad  vlad1

если бы не случайное второе поле в file1, то такой вариант подошел бы, но если во втором поле file1 появляется цифра или слово, то уникальная строка из file2 не всегда вставляется первой, то есть если в первом файле вместо строки «ivan ivan1» будет «ivan 0»? то после объединения будет

$ comm -3 file1 file2
ivan  0
ivan  1
ivan  ivan2
ivan  ivan3
petr  2
petr  petr1
petr  petr2
vlad  3
vlad  vlad1

nerve ★★
() автор топика
Ответ на: комментарий от unterwulf

однако!

авторские комментарии были бы весьма уместны. если в коде еще попадаются знакомые слова, то вот это

!dictdone && !dictfile { dictfile = FILENAME }
FILENAME != dictfile { dictdone = 1 }
!dictdone { dict[$1] = $2; next }
вообще не понятно

nerve ★★
() автор топика
Ответ на: комментарий от nerve

если в коде еще попадаются знакомые слова, то вот это <...> вообще не понятно

Задача этого блока — считать первый переданный скрипту файл в ассоциативный массив dict.

!dictdone && !dictfile { dictfile = FILENAME }

Если ни одна из переменных dictdone и dictfile не задана, значит мы тольно начинаем обрабатывать первый файл, который по условию словарь. Запоминаем имя этого файла, чтобы после определить момент, когда мы переключимся на следующий файл.

FILENAME != dictfile { dictdone = 1 }

Если имя текущего файла не равно dictfile, значит мы дочитали словарь до конца и переключились на следующий файл. Устанавливаем флажок dictdone.

!dictdone { dict[$1] = $2; next }

Если флажок dictdone не установлен, значит мы все ещё читаем словарь. Заносим данные из очередной строки в массив dict и начианаем обработку следующей строки.

unterwulf
()
Ответ на: комментарий от nerve

Пока писал объяснение стало ясно, что можно то же самое сделать короче и без флажков. Например, так:

FNR == 1 { filenum++ }
filenum == 1 { dict[$1] = $2; next }
unterwulf
()
Ответ на: комментарий от unterwulf

Ваш скрипт работает идеально даже если исходные два файла совершенно не похожи на тестовые с «Иванами». я добавил только другой разделитель полей.

nerve ★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.