LINUX.ORG.RU

gawk: уменьшить размер таблицы

 


0

1

Добрый день! Просьба помочь разобраться в проблеме. Есть таблица A.txt

A	B	B	C	D	D	D	E
1	2	3	4	5	6	6	7
8	9	10	11	12	13	6	14
15	16	17	18	19	20	6	21
22	23	24	25	26	27	6	28

На выходе необходимо получить таблицу B.txt

A	B;B	C	D;D;D	E
1	2;3	4	5;6;6	7
8	9;10	11	12;13;6	14
15	16;17	18	19;20;6	21
22	23;24	25	26;27;6	28

Объединение полей производится при наличии одинаковых заголовков (предполагается, что поля отсортированы по именам). Не пойму, как это сделать, ведь gawk обрабатывает файл построчно. То есть если сделать {if ($i=$i+1)} он обработает только первую строку.



Последнее исправление: xseed (всего исправлений: 2)

Мой быдлокод:

cat a.txt | gawk ' BEGIN{FS=" "; got=0; max=0; arr[0]=0} {if(!got) {lastv=""; for(i=1;i<=NF;i++){if(lastv!=$i){lastv=$i;if(i>1){max=max+1}};arr[i]=max;}; got=1}} {str=""; for(j=0;j<=max;j++){strtmp=""; for(i=1;i<=NF;i++){if(arr[i]==j){if(strtmp==""){strtmp=$i}else{strtmp=strtmp";"$i}}} str=str" "strtmp} print str} '

AWK почти не знаю, может, можно написать и по короче.

PHPFan
()

Вначале обрабатываешь заголовки, чтобы получить одинаковые и определить в каких они полях, а потом уже построчно весь файл, я так понимаю. В awk есть специально для этого директива BEGIN позвляющая определенный код выполнить только один раз.

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

Без пробела впереди:

 cat a.txt | awk ' BEGIN{FS=" "; got=0; max=0; arr[0]=0} {if(!got) {lastv=""; for(i=1;i<=NF;i++){if(lastv!=$i){lastv=$i;if(i>1){max=max+1}};arr[i]=max;}; got=1}} {str=""; for(j=0;j<=max;j++){strtmp=""; for(i=1;i<=NF;i++){if(arr[i]==j){if(strtmp==""){strtmp=$i}else{strtmp=strtmp";"$i}}} if(j==0){str=strtmp}else{str=str" "strtmp}} print str} '
PHPFan
()

gawk

завидуй:

ruby -e 'puts $<.lines.map(&:split).transpose.group_by(&:first).map{
    |_,v| :zip.to_proc[*v].map{|a| a.join";"}
}.transpose.map{|a| a.join" "}'  \
| column -t
anonymous
()
Ответ на: комментарий от Xenius

Xenius, а конкретно, как директива BEGIN работает? На примере можете показать?

Еще почитал немного мануал по awk, вроде как есть возможность использовать массивы. Как представить таблицу в виде двумерного массива в awk? Можно ли ссылаться при обработке каждой строки на первую строку таблицы и если заголовки полей равны, то делать объединение через ;?

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

И еще getline заинтересовал. Можно его как-то использовать для решения этой задачи?

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

На примере — смотри выше. Как работает подробно описано в официальном руководстве. (info awk или на официальном сайте)

Просто код после BEGIN выполняется один раз, а не для каждой строки.

Xenius ★★★★★
()
Последнее исправление: Xenius (всего исправлений: 1)
Ответ на: комментарий от PHPFan
cat A.txt | gawk " BEGIN{FS=\" \"; got=0; max=0; arr[0]=0} {if(!got) {lastv=\"\"; for(i=1;i<=NF;i++){if(lastv!=$i){lastv=$i;if(i>1){max=max+1}};arr[i]=max;}; got=1}} {str=\"\"; for(j=0;j<=ma
x;j++){strtmp=\"\"; for(i=1;i<=NF;i++){if(arr[i]==j){if(strtmp==\"\"){strtmp=$i}else{strtmp=strtmp\";\"$i}}} if(j==0){str=strtmp}else{str=str\"\t\"strtmp}} print str} "

Помогло, спасибо

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