Слияние строк (с совпадающим значением)

На самом деле это единственный раздел про unix на этом форуме

Модераторы: /dev/random, Модераторы разделов

Ответить
gunb1rd
Сообщения: 5

Слияние строк

Сообщение gunb1rd »

Доброй ночи, друзья! Прошу совета. Имеется такой текст:

Код: Выделить всё

ch1:512
ch2:2048
ch3:1024
ch4:2048
ch5:4096
ch1:192.95.52.1
ch3:172.94.51.0
ch5:8.8.8.8


Это channel, speed и ip, необходимо добавить ip к speed, в строке у которой, такойже channel. Чтобы получилось вот так:

Код: Выделить всё

ch1:512:192.95.52.1
ch3:1024:172.94.51.0
ch5:4096:8.8.8.8


За ранее благодарю за помощь!


Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5282
ОС: Gentoo

Re: Слияние строк

Сообщение /dev/random »

join -t : <(grep -v '[.]' in.txt) <(grep '[.]' in.txt)

Используется bash-специфичная конструкция, для других шеллов нужно переделывать.
Спасибо сказали:
gunb1rd
Сообщения: 5

Re: Слияние строк

Сообщение gunb1rd »

Почемуто не все файлы обрабатывает как надо. Допустим файл ./146 обработало не до конца

Код: Выделить всё

[freebsd]$ cat 146
ch1:6144
ch3:2048
ch4:2048
ch7:1024
ch8:1024
ch9:5120
ch10:512
ch11:2048
ch12:2048
ch13:5120
ch14:5120
ch1:1.1.1.1
ch3:1.1.1.1
ch7:2.2.2.2
ch11:3.3.3.3
ch13:4.4.4.4
[freebsd]$ join -t : <(grep -v '[.]' ./146) <(grep '[.]' ./146)
ch1:6144:1.1.1.1
ch3:2048:1.1.1.1
ch7:1024:2.2.2.2


а файл ./156 обработало как надо. вроде бы различий в файле нет никаких, не подскажете, в чём проблема?

Код: Выделить всё

[freebsd]$ cat 156
ch1:3072
ch3:1024
ch4:1024
ch5:2048
ch6:2048
ch9:3072
ch10:512
ch11:3072
ch12:3072
ch13:3072
ch14:3072
ch1:1.1.1.1
ch3:2.2.2.2
ch5:2.2.2.2
ch9:4.4.4.4
ch11:5.5.5.5
ch13:6.6.6.6
[freebsd]$ join -t : <(grep -v '[.]' ./156) <(grep '[.]' ./156)
ch1:3072:1.1.1.1
ch3:1024:2.2.2.2
ch5:2048:2.2.2.2
ch9:3072:4.4.4.4
ch11:3072:5.5.5.5
ch13:3072:6.6.6.6



Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5282
ОС: Gentoo

Re: Слияние строк

Сообщение /dev/random »

join'у требуется алфавитная сортировка, а в ваших файлах - числовая. Из первого примера этого не было видно, так что не сообразил.

Тогда так:

join -t : <(grep -v '[.]' in.txt | sort -t : -k 1,1) <(grep '[.]' in.txt | sort -t : -k 1,1)
Спасибо сказали:
gunb1rd
Сообщения: 5

Re: Слияние строк

Сообщение gunb1rd »

Спасибо огромное! Всё спарсил :)

Правда я пока не знаю почему и как это работает, но обещаю в скором времени разобраться =) С bash только начал знакомтсво.

Ещё раз спасибо! :)
Спасибо сказали:
gunb1rd
Сообщения: 5

Re: Слияние строк

Сообщение gunb1rd »

будте добры, подскажите ещё, как слить 2 списка:

file1:

Код: Выделить всё

name1:192.168.0.1/29
name2:172.13.15.16/32
name3:192.168.0.2/32
name4:172.13.15.17/30
name5:192.168.0.3/28
name6:172.13.15.18/32


file2:

Код: Выделить всё

ch1:12288:192.168.0.1
ch11:2048:192.168.0.2
ch13:512:192.168.0.3


Чтобы на выходе получить только то что в file2 + name из file1, ip которых равны

file3

Код: Выделить всё

ch1:12288:192.168.0.1:name1
ch11:2048:192.168.0.2:name3
ch13:512:192.168.0.3:name5



За ранее спасибо
Спасибо сказали:
Аватара пользователя
SLEDopit
Модератор
Сообщения: 4823
Статус: фанат консоли (=
ОС: GNU/Debian, RHEL

Re: Слияние строк

Сообщение SLEDopit »

gunb1rd писал(а):
01.02.2014 01:36
Правда я пока не знаю почему и как это работает

/dev/random писал(а):
01.02.2014 01:18
join -t : <(grep -v '[.]' in.txt | sort -t : -k 1,1) <(grep '[.]' in.txt | sort -t : -k 1,1)
join -- объединяет файлы по общему полю
-t : -- в качестве разделитя использовать :
<() -- подробно про такую штуку можно почитать тут
grep -v '[.]' in.txt | sort -t : -k 1,1 -- вывести файл в stdout, удалив все строки с точкой и отсортировать , использую разделитель поля :

По вашей второй просьбе будет примерно так:

Код: Выделить всё

join -t : -1 2 -2 3 <(sort -k1 -t: 1 | sed 's=/.*==') <(sort -k3 -t: 2)

Попробуйте разобраться самостоятельно, как это работает
UNIX is basically a simple operating system, but you have to be a genius to understand the simplicity. © Dennis Ritchie
The more you believe you don't do mistakes, the more bugs are in your code.
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5282
ОС: Gentoo

Re: Слияние строк

Сообщение /dev/random »

SLEDopit писал(а):
01.02.2014 12:53

Код: Выделить всё

join -t : -1 2 -2 3 <(sort -k1 -t: 1 | sed 's=/.*==') <(sort -k3 -t: 2)

Я бы всё-таки рекомендовал для sort задавать и начальное, и конечное поле, так как join ожидает сортировку по одному полю, а не по всем, начиная с указанного. Т.е. не "-k1", а "-k1,1".
Спасибо сказали:
gunb1rd
Сообщения: 5

Re: Слияние строк

Сообщение gunb1rd »

Спасибо. Постараюсь разобраться.

Код: Выделить всё

join -t : -1 2 -2 3 <(sort -k1,1 -t: ips.lst | sed 's=/.*==') <(sort -k1,1 -t: name.lst)


не работает. выдаёт тот же список name.lst только с : в начале строки
Спасибо сказали:
Аватара пользователя
/dev/random
Администратор
Сообщения: 5282
ОС: Gentoo

Re: Слияние строк

Сообщение /dev/random »

gunb1rd писал(а):
01.02.2014 13:35
Спасибо. Постараюсь разобраться.

Код: Выделить всё

join -t : -1 2 -2 3 <(sort -k1,1 -t: ips.lst | sed 's=/.*==') <(sort -k1,1 -t: name.lst)


не работает. выдаёт тот же список name.lst только с : в начале строки

join -t : -1 2 -2 3 <(sort -k2,2 -t: name.lst | sed 's=/.*==') <(sort -k3,3 -t: ips.lst)

Или, если важен именно такой порядок полей, как в образце (join по умолчанию ставит общее поле в начало), то так:

join -t : -1 2 -2 3 <(sort -k2,2 -t: name.lst | sed 's=/.*==') <(sort -k3,3 -t: ips.lst) -o 2.1,2.2,0,1.1
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Слияние строк

Сообщение drBatty »

gunb1rd
я хотел дать sed-скрипт, но подумав решил, что гвозди лучше забивать молотком, а сливать строки join'ом.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить