LINUX.ORG.RU

SED-обработка большого текстового файла.

 ,


0

1

Имеем файл исписаный строками «*|*|*|*|*|URL». Во всём тексте не последовательно имеется не мало совершенно разных по содержанию строк, но с одним URL. Нужно всего-то как у Микелианжело «отсечь всё лишнее» - оставить только уникальные URL. В наличии bash, скромные познания sed. Гугл помог вот таким примером:

Удалить дублирующиеся непоследовательные строки файла. Острожнее с переполнением размера буфера, занятой памяти, лучше используйте GNU sed!

sed -n 'G; s/n/&&/; /^([ -~]*n).*n1/d; s/n//; h; P'
Но мне эта последовательность как-то не нравится...

★★

оставить только уникальные URL

cut -d \| -f 6 | sort -u

lazyklimm ★★★★★ ()

Нужно всего-то как у Микелианжело «отсечь всё лишнее» - оставить только уникальные URL

Тебе нужны только URL? Если нет, то в случае одинаковых URL какое из описаний оставлять?

Если да, то

awk -F'|' '{print $6}' file | sort | uniq
derlafff ★★★★★ ()
Ответ на: комментарий от derlafff

Приношу извинения...

Мне нужны строки с уникальными URL, а не сами URL (такую выборку я могу и сам организовать опираясь на минимум утилит).

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

формат строки: «*|*|*|*|*|URL»

Так что нужен парсер выделяющий последний элемент строки (всё, что осталось за последним символом «|») и опирается на его уникальность для сбора нового документа (в котором все ссылки будут уникальными). Сортировка не нужна и даже больше того - её желательно избежать.

zzdnx ★★ ()
Последнее исправление: zzdnx (всего исправлений: 1)
Ответ на: комментарий от lazyklimm

а остальные поля?

а остальные поля?

Они не важны. Главное - убрать строки с уже имеющимися URL.

и вообще, возьми уже нормальный браузер

Чем Вам не нравится мой текущий браузер? Не нармальный браузер? - Тогда какой из них НОРМАЛЬНЫЙ? о_О

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

Как я понимаю: пронумеровать строки, сортировать по последнему полю, потом сортировать по «заголовку» (номера строк), и в конце очиска - удаление нумерации. Много действий... Но лучшего варианта пока не предложено.

zzdnx ★★ ()
Ответ на: а остальные поля? от zzdnx

Они не важны. Главное - убрать строки с уже имеющимися URL.

есть две строки с одним URL, но различающимися полями. Какую брать? Если любую - то получается, что остальные поля не важны, если не любую - то как определить, какую оставить?

Чем Вам не нравится мой текущий браузер?

Ну, я так понимаю ты для него костылишь?

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

ты для него костылишь?

нет. Не для браузера, а для самодельного бота-паучка, который вытаскивает только то что мне нужно из сети.

есть две строки с одним URL, но различающимися полями. Какую брать?

Оставить первую, а вторую-третью-n`ную - удалить за дубликатность URL.

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

Не для браузера, а для самодельного бота-паучка, который вытаскивает только то что мне нужно из сети.

запихивай в базу, вытаскивай запросом

Оставить первую, а вторую-третью-n`ную - удалить за дубликатность URL.

а почему именно первую?

lazyklimm ★★★★★ ()
nawk -F'|' '{print $6}' | sort -u
anonymous ()
Ответ на: комментарий от derlafff

Уважаемые, вы так аккуратно использовали sort и uniq (вместо sort -u), но, видимо, не знаете, что оригинальный awk не понимает -F. Либо nawk либо gawk.

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

запихивай в базу, вытаскивай запросом

Для меня это пока сложно и не понятно в реализации. Я и примитивную БД создать не могу, не то чтобы запросом из неё нечто вытягивать из cli в текстовый документ.

а почему именно первую?

Особой причины такого выбора нет. Думаю что при обработке sed/awk оставить её будет проще всего.

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

оригинальный awk не понимает -F

а кто-то его использует?

lazyklimm ★★★★★ ()
Ответ на: ну можно и в лоб от lazyklimm

«cut -d \| -f Х» оставит только URL`ы (обрежет все предшествующие поля до искомого поля Х), а мне нужны только ссылки, мне нужны строки с уникальными URL в окончании.

zzdnx ★★ ()
Последнее исправление: zzdnx (всего исправлений: 1)
Ответ на: комментарий от lazyklimm

Извини, затупил. Теперь разобрался. Идеальная конструкция.

Я думал решить это через SED потому что она умеет хранить буфер и сопоставлять с регуляркой.

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

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

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

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

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

А можно узнать у Вас как реализовать следующее: Вышеупомянутый файл (с внутренним форматом в виде таблицы *|*|*|*|*) запихнуть в sql, потом сделать вышеописаную выборку строк в новый текстовый файл?

Просто в моём случае имеется трудность незнания sql/ruby/python/other_СЯП, а такое решение может не хило облегчить мне жизнь (за одно и появятся первые навыки работы с БД и теми языками, которых не знаю).

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

Метров 400 или даже более того

всего-то?
не парься с SED, возьми gVIM
с макросами он очень даже не плох как комбайн по обработке данных
главное знать что тебе точно нужно сделать
я так из дампа базы в 1.2 гига выдернул весь нужный мне контент минут за 10-20

q11q11 ★★★★★ ()
Последнее исправление: q11q11 (всего исправлений: 1)
Ответ на: комментарий от ZuBB

3P/ruby + sqlite и не виеживайся

А если я этого не знаю - изучить? А если на это нет времени - искать готовые решения?

Изучать-то я и сам хочу, но сейчас нет времени на изучение нового материала (нужно результаты выдавать) + мой инглицкий на уровне «с кОла, да на лебедя», и обычные мануалы на буржуйском мне осваивать тяжко.

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

я так из дампа базы в 1.2 гига выдернул весь нужный мне контент минут за 10-20

Мне как раз это и нужно. Пусть сейчас масштабы поменьше, но их рост - это только вопрос времени. gVIM тут чем и как помочь может?

zzdnx ★★ ()

Имеем файл исписаный строками «*|*|*|*|*|URL». Во всём тексте не последовательно имеется не мало совершенно разных по содержанию строк, но с одним URL. Нужно всего-то как у Микелианжело «отсечь всё лишнее» - оставить только уникальные URL.

самый быстрый метод - сначала отрезать лишнее, потом sort -u. Если в URL не бывает |, тогда типа:

sed 's/.*|//' | sort -u
не думаю, что есть способ быстрее (тут даже свой парсер с БД на асме ИМХО не поможет).

Но мне эта последовательность как-то не нравится...

правильно, что не нравится. Такое работает, но только на тестовых примерах.

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

Мне как раз это и нужно. Пусть сейчас масштабы поменьше, но их рост - это только вопрос времени. gVIM тут чем и как помочь может?

(g)VIM умеет выполнять команды sed. И внешние команды. Т.е. что-то типа

:%s/.*|//
!!sort -u

должно помочь. Вот только зачем?

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

Пусть сейчас масштабы поменьше, но их рост - это только вопрос времени

тогда пока не поздно - почитай туториал по sql,

у тебя для начала задача достаточно простая:

- создать таблицу с полями соответствующих типов

- для каждой строки делать insert (если в шелле - придется разделители «|» сменить на запятые и нужное обернуть в кавычки)

а с потом уже можно с языком запросов разбираться

русская дока по sqlite нпример вот: http://sb-money.ru/sqlite.php?page=21

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

русская дока по sqlite

Спасибо за помощь. Буду ковырять.

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

тогда пока не поздно - почитай туториал по sql,

ИМХО здравый совет. На будущее всё равно костыль из sed не покатит. Нужна БД.

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

URL будут во всех строках. Гарантировано. И нужны не ссылки, а строки с этими ссылками.

а... Тогда можно обойтись одной только GNU sort (ЕМНИП не везде она есть). Sort умеет сортировать полями, и если полей всегда одно число, то задаём разделитель:

-t, --field-separator=SEP use SEP instead of non-blank to blank transition

-k, --key=KEYDEF sort via a key; KEYDEF gives location and type

KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a field number and C a character position in the field; both are origin 1, and the stop position defaults to the line's end. If neither -t nor -b is in effect, characters in a field are counted from the beginning of the preceding whitespace. OPTS is one or more single-letter ordering options [bdfgiMhnRrV], which over‐ ride global ordering options for that key. If no key is given, use the entire line as the key.

тогда sort тупо отсортирует всё по url (и выкинет лишнее)

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

URL будут во всех строках. Гарантировано. И нужны не ссылки, а строки с этими ссылками.

а... Тогда можно обойтись одной только GNU sort (ЕМНИП не везде она есть). Sort умеет сортировать полями, и если полей всегда одно число, то задаём разделитель:

-t, --field-separator=SEP use SEP instead of non-blank to blank transition

-k, --key=KEYDEF sort via a key; KEYDEF gives location and type

KEYDEF is F[.C][OPTS][,F[.C][OPTS]] for start and stop position, where F is a field number and C a character position in the field; both are origin 1, and the stop position defaults to the line's end. If neither -t nor -b is in effect, characters in a field are counted from the beginning of the preceding whitespace. OPTS is one or more single-letter ordering options [bdfgiMhnRrV], which over‐ ride global ordering options for that key. If no key is given, use the entire line as the key.

тогда sort тупо отсортирует всё по url (и выкинет лишнее)

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

отсортирует всё по url (и выкинет лишнее)

Почему-то в этом примере главная задача оказалась как побочный эффект (в скобочках), а не нужная - на месте главной. И ещё - я очень плох в английском, так что буду пока переводить...

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

gVIM тут чем и как помочь может?

открываешь файл, записываешь нужные тебе макросы, выполняешь, получаешь нужный тебе контент
очевидно же

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

Я не умею работать даже с vim. Откуда мне знать про макросы и на каких языках, куда и как их писать (про исполнение молчу)?..

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

Почему-то в этом примере главная задача оказалась как побочный эффект (в скобочках), а не нужная - на месте главной.

ИМХО тебе нужно таки про SQL читать. Наверное таки про MySQL больше всего книжек/статей по-русски. Хотя SQLite попроще.

И ещё - я очень плох в английском, так что буду пока переводить...

ну на пальцах:

сортировка по полю №4

$ echo "1 2 3 4
2 3 6 2
1 1 1 0
1 7 7 3
1 9 1 2
0 0 0 0" | sort -k4
0 0 0 0
1 1 1 0
1 9 1 2
2 3 6 2
1 7 7 3
1 2 3 4
сортировка по полю №4, но выкидываем повторы
$ echo "1 2 3 4
2 3 6 2
1 1 1 0
1 7 7 3
1 9 1 2
0 0 0 0" | sort -k4 -u
1 1 1 0
2 3 6 2
1 7 7 3
1 2 3 4
тут поля разделяются пробелом, но можно и |.

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

эээ, а что ты знаешь вообще и зачем тебе (при малых знаниях) внезапно понадобилось парсить 400мегов текста?

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

В том и дело, что в этом примере происходит упорядочивание по полю, а этого хотелось бы избежать (хотя это и не критично в данном случае). Строки дописываются в конец (то есть ссылки появляются в файле «по возрасту»: чем старее, тем ближе к началу файла).

Однако пример очень хороший.

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

Зачем: работа с очень большим количеством запросов в сеть. Отсюда и размеры файла. И он будет не один такой.

Парсить зачем: дальнейшая оработка. И предвижу следующий вопрос: А почему сразу не в БД?

Дальнейший конвейер на входе принимает только текст (при том для корректной работы этот текст должен быть ожидаемо отформатирован) и с СУБД я толком не знаком, поэтому не в состоянии решить вопрос грамотно. Плюс очень хочется избежать «лишней» работы типа создания промежуточных файлов и тому подобное.

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

В том и дело, что в этом примере происходит упорядочивание по полю, а этого хотелось бы избежать (хотя это и не критично в данном случае). Строки дописываются в конец (то есть ссылки появляются в файле «по возрасту»: чем старее, тем ближе к началу файла).

не так. Это неустойчивая сортировка. Строки дописываются как Патрег на душу положит. Что-бы строки сохраняли своё положение, надо использовать устойчивую сортировку

-s, --stable stabilize sort by disabling last-resort comparison

http://ru.wikipedia.org/wiki/Устойчивая_сортировка

(устойчивая часто намного дольше работает)

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

устойчивая часто намного дольше работает

Ясен фиг, что дольше. Там алгоритмы более сложные (и по крайней мере должно больше памяти использоваться).

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

Ясен фиг, что дольше.

неясен. Например списки сортируют слиянием, а она устойчивая. Вот если специальный случай сортировки «на месте», то да, неустойчивая сортировка должна быть дольше.

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