Переформатировать данные с помощью awk - PullRequest
0 голосов
/ 29 июня 2018

У меня есть набор данных, который содержит строки UUID, за которыми следуют местоположения и идентификаторы транзакций. UUID разделены точкой с запятой (';'), а транзакции разделены вкладками, как показано ниже:

01234;LOC_1=ABC    LOC_1=BCD    LOC_2=CDE
56789;LOC_2=DEF    LOC_3=EFG

Я заранее знаю все коды мест. Я хочу преобразовать эти данные в формат, который я могу загрузить в SQL / Postgres для анализа, например:

01234;LOC_1=ABC
01234;LOC_1=BCD
01234;LOC_2=CDE
56789;LOC_2=DEF
56789;LOC_3=EFG

Я почти уверен, что могу сделать это легко, используя awk (или аналогичный), просматривая идентификаторы местоположения из файла (например, LOC_1) и сопоставляя любой экземпляр идентификатора местоположения и распечатывая его рядом с UUID. Я еще не смог сделать это правильно, и любая помощь очень ценится!

Мой файл местоположений называется location, а мой набор данных - data. Обратите внимание, что я могу отредактировать исходный файл или записать результаты в новый файл, либо в порядке.

Ответы [ 5 ]

0 голосов
/ 01 июля 2018

Это может сработать для вас (GNU sed):

sed -r 's/((.*;)\S+)\s+(\S+)/\1\n\2\3/;P;D' file

Повторно заменяйте пробел между местоположениями новой строкой, за которой следует UUID и ;, печатая / удаляя каждую строку в том виде, в котором она отображается.

0 голосов
/ 30 июня 2018

Как насчет без цикла или без разделения следующим образом (учитывая, что Input_file такой же, как только показанные образцы)

awk 'BEGIN{FS=OFS=";"}{gsub(/[[:space:]]+/,"\n"$1 OFS)} 1'  Input_file
0 голосов
/ 29 июня 2018

Вы комментируете, зная расположение, и файл сопоставления вызывает у меня подозрение, что ваш пример, похоже, сделал не совсем то, о чем вас спрашивают, - но вам кажется, что вы хотите переформатировать каждый набор табуляции с разделителями LOC= значения в строку с их UUID впереди.

Если это так, то сработает:

awk ' BEGIN {OFS=FS=";"} {split($2,locs,"\t"); for (n in locs) { print $1,locs[n]}}' 

Дано:

$ cat -A data.txt
 01234;LOC_1=ABC^ILOC_1=BCD^ILOC_2=CDE$
 56789;LOC_2=DEF^ILOC_3=EFG$

Тогда:

$ awk ' BEGIN {OFS=FS=";"} {split($2,locs,"\t"); for (n in locs) { print $1,locs[n]}}' data.txt
 01234;LOC_1=ABC
 01234;LOC_1=BCD
 01234;LOC_2=CDE
 56789;LOC_2=DEF
 56789;LOC_3=EFG

Блок BEGIN {OFS=FS=";"} устанавливает разделитель входа и выхода на;.

Затем для каждой строки мы разбиваем второе поле на массив с именем locs, разделяя его на табуляцию, через - split($2,locs,"\t")

А затем перебрать locs, печатая UUID и каждое значение loc - for (n in locs) { print $1,locs[n]}

0 голосов
/ 29 июня 2018

awk без использования split: используйте точку с запятой или в качестве разделителя полей

awk -F'[;\t]' -v OFS=';' '{for (i=2; i<=NF; i++) print $1,$i}' file
0 голосов
/ 29 июня 2018

Я не думаю, что вам нужно сопоставлять с известным списком мест; Вы должны быть в состоянии просто напечатать каждую строку, как вы идете:

$ awk '{print $1; split($1,a,";"); for (i=2; i<=NF; ++i) print a[1] ";" $i}' file
01234;LOC_1=ABC
01234;LOC_1=BCD
01234;LOC_2=CDE
56789;LOC_2=DEF
56789;LOC_3=EFG
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...