LINUX.ORG.RU

Как в bash свести значения, указанные в столбце в строку?

 ,


1

1

Здравствуйте.

Есть файл вида:

111|234|значение 1
112|567|значение 2
113|234|значение 3
114|234|значение 4
115|567|значение 5
116|234|значение 6
117|567|значение 7

Подскажите, пожалуйста, как из него получить файл:

234|значение 1,значение 3,значение 4,значение 6
567|значение 2,значение 5,значение 7



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

Ответ на: Без обид. от sqq

Спасибо. Это конкретный практический вопрос, решить который у меня на данный момент не хватает компетенции. А свои лабы я отсдавал лет так 25 назад.

Neuro75
() автор топика
$ cat input
111|234|значение 1
112|567|значение 2
113|234|значение 3
114|234|значение 4
115|567|значение 5
116|234|значение 6
117|567|значение 7
$ cat code
{
    data[$2] = ($2 in data ? data[$2] "," : "") $3;
}

END {
    for (id in data) {
        print id "|" data[id]
    }
}
$ awk -f code -F'|' < input
234|значение 1,значение 3,значение 4,значение 6
567|значение 2,значение 5,значение 7
xaizek ★★★★★
()

Такие вещи ведь действительно тянут на лабораторку ибо решаются за минуту.

#!/bin/awk -f
BEGIN { FS="|" }
{ if(!a[$2]) a[$2]=$2"|"$3; else a[$2]=a[$2]","$3 }
END { for(i in a) print a[i] }

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

Спасибо за ответы ) буду пробовать.

Такие вещи ведь действительно тянут на лабораторку ибо решаются за минуту.

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

Еще раз спасибо.

Neuro75
() автор топика
$ cat /tmp/wow
111|234|value 1
112|567|value 2
113|234|value 3
114|234|value 4
115|567|value 5
116|234|value 6
117|567|value 7

$ perl -F'\|' -nale '$a{$F[1]} = [@{$a{$F[1]}}, $F[2]] }{ foreach $k (keys %a) { print("$k|" . join(",", @{$a{$k}}) )  }' /tmp/wow
567|value 2,value 5,value 7
234|value 1,value 3,value 4,value 6
anonymous
()

А что ты потом будешь делать с этими 567|значение 2,значение 5,значение 7? С ними же не очень удобно работать, ИМХО. Не лучше ли оставить

567|значение 2
567|значение 5
567|значение 7
```?
anonymous
()

если бы не sort, сказал бы что чистый баш, а так почти

однострочник

IFS='|';  p='_'; while read a k v; do if [ $p == $k ]; then echo -n "$v,"; else p=$k; echo ""; echo -n "$k|"; fi; done <<< $(sort -t'|' -k2n aaa.txt); echo ""

форматированный код

IFS='|'
p='_'
while read a k v; do
 if [ $p == $k ]; then
    echo -n "$v,"
 else
    p=$k
    echo ""
    echo -n "$k|"
 fi
done <<< $(sort -t'|' -k2n input.txt)
echo ""

результат

234|значение 3,значение 4,значение 6,
567|значение 5,значение 7,

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

А что ты потом будешь делать с этими 567|значение 2,значение 5,значение 7? С ними же не очень удобно работать, ИМХО.

Я их возьму из таблицы с описанием доп.изображений opencart'а и засуну в фид фейсбука, который требует доп.изображения в формате url1,url2,url3.

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

Тем более, есть хорошая книжка

О! Спасибо! пробежал по оглавлению - полезная книга. Утянул читать.

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

если бы не sort, сказал бы что чистый баш, а так почти

Ну раз у вас юзается «<<<», то можно смело заюзать полноценный bash, то есть ассоциативные массивы и сделать аналог приведенных реализаций на awk без sort:

#!/usr/bin/env bash
declare -A a
IFS='|'
while read num sval val; do
        if [[ -z ${a["$sval"]} ]]; then
                a["$sval"]="$sval|$val"
        else
                a["$sval"]="${a["$sval"]},$val"
        fi

done
for sval in "${a[@]}"; do
        echo "$sval"
done

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