bash: очистить и объединить данные - PullRequest
0 голосов
/ 27 января 2019

У меня есть три CSV-файла, содержащие разные данные для общего объекта.Они представляют данные о различных коллекциях предметов на работе.Эти объекты имеют уникальные коды.Количество файлов не имеет значения, поэтому я решу эту проблему двумя.У меня есть удобный рецепт для объединения этих файлов с использованием join, но чистящая часть убивает меня.

Файл Фрагмент - содержит уникальные данные.Также ошибка каталогизации E B.

B    547
J    65
EB   289
E B  1
CO   8900
ZX   7

Фрагмент файла B - уникальные данные о различном измерении объектов.

B    5
ZX   67
SD   4
CO   76
J    54
EB   10

Обратите внимание, что файл B содержит не общий кодс файлом A.

Теперь я представляю вам «официальный» канон кодов, предназначенных для этого набора объектов:

B
CO
ZX
J
EB

Обратите внимание, что файл B содержит неканонический код с данными,Это должно быть зафиксировано и задокументировано.То же самое с неверным кодом в файле A.

Конечная цель: запустить тренд и статистику для коллекций, используя различные поля из нескольких отчетов.Они в основном соответствуют канону, но есть странности из-за ошибок каталогизации и кодов, которые больше не используются.

Конечный результат цели после слияния / объединения:

B    547    5
J    65     54
EB   289    10
CO   8900   76
ZX   7      67

Итак, моя первая идея былаиспользовать для этого grep -F -f, используя канонические коды в качестве списка поиска, затем объединить с join.Проблема в том, что с однобуквенными кодами это слишком много.Казалось бы, работа для awk, где он может работать с tab разделителями и REGEX чудовищными кодами.Я не уверен, однако, как заставить awk использовать список для просеивания других файлов.Один join справится со всем этим?Может быть, я сливаюсь с join или paste, затем просеиваю чудаков?Какой метод является наименее хрупким и с большей вероятностью обрабатывает крайние случаи, как пьяный каталогизатор?

Если вы думаете: «Чувак, это лучше сделать с помощью Perl или Python ... и т. Д.».Я весь во внимании.Нет правил, мне просто нужно доставить!

Ответы [ 2 ]

0 голосов
/ 27 января 2019

Попробуйте это (GNU awk):

awk 'BEGIN{FS=OFS="\t";}ARGIND==1{c[$1]++;}ARGIND==2{b[$1]=$2}ARGIND==3{if (c[$1]) {print $1,$2,b[$1]+0; delete b[$1];} else {if(tolower($1)~"[a-z]+ +[a-z]+")print>"error.fileA"; else print>"oddball.fileA";}}END{for (i in b) {print i,0,b[i] " (? maybe?)";print i,b[i] > "oddball.fileB";}}' codes fileB fileA

Будет создано error.fileA, oddball.fileA, если такие строки существуют, oddball.fileB.
Нормальный вывод не записывал в файл, вы можете написать > самостоятельно, когда результаты в порядке:

B   547 5
J   65  54
EB  289 10
CO  8900    76
ZX  7   67
SD  0   4 (? maybe?)

Трудно было читать ваше описание, не уверен, что это то, что вы хотите.
Во всяком случае, это легко улучшить этот код awk.

Вы можете изменить на FILENAME=="file1" или FILENAME==ARGV[1], если ARGIND не работает.

0 голосов
/ 27 января 2019

Ваш вопрос говорит о том, что данные в формате csv, но, основываясь на ваших примерах, я предполагаю, что это tsv. Я также предполагаю, что E B должен заканчиваться на выходе выброса и что значения NA должны быть заполнены 0.

С учетом этих допущений может быть достаточно следующего:

sort -t $'\t' -k 1b,1 fileA > fileA.sorted && sort -t $'\t' -k 1b,1 fileB > fileB.sorted
join -t $'\t' -a1 -a2 -e0 -o auto fileA.sorted fileB.sorted > out
grep -f codes out > out-canon
grep -vf codes out > out-oddball

Содержимое файла codes:

^B\s
^CO\s
^ZX\s
^J\s
^EB\s

Результат:

$ cat out-canon
B       547     5
CO      8900    76
EB      289     10
J       65      54
ZX      7       67

$ cat out-oddball
E B     1       0
SD      0       4
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...