LINUX.ORG.RU

grep в разные файлы за один проход

 ,


0

2

Доброго!

cat file.txt

foo whatewerfoo
bar whateverbar
xyz whateverxyz

Сейчас я делаю так:

for names in foo bar xyz;do
grep $names file.txt >$names.txt
done

что требует от меня проходов по файлу по числу образцов. Можно ли сделать это за один проход?



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

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

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

Как и любой фильтр, grep выводит в stdout, так что как обычно - надо парсить stdout. Если у вас каких-то особенных ключей типа -ABC и прочих бинарных данных нет, то и grep для bash не надо, считывайте файл построчно, делайте [[ «$str» =~ regex_pattern ]] и записывайте в выходные файлы.

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

Т.е., предлагается в конвеер поставить это сравнение и по резулльтату писать в нужный файл? Мне кажется, это адово долго.

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

Где конвеер? Обычный while read str ; do parse «$str» ; done < $in_file, где в parse() нужное вам количество сравнений и при успешности - дозапись в выходные файлы. Оно, конечно, если прохачить grep на предмет добавления опций, где результат сравнения c каждым pattern бы записывался бы в разный файл было б быстро, но по сравнению с мноокрытным вызовом grep что тут предлагалось мой вариант будет быстрым.

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

т.е., вот так?

cat file.txt|while read string;do
[[ grep foo file.txt ]] && echo $string >>foo.txt
[[ grep bar file.txt ]] && echo $string >>bar.txt
[[ grep xyz file.txt ]] && echo $string >>xyz.txt
done

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

неплохо положить файл в память перед грепаньем.

Deleted
()
Ответ на: комментарий от rusya_rr

Не, [[ - это уже вызов команды, да и ведь сказал, что grep не нужен. Получилось, впрочем, не так то просто:

#!/bin/bash

declare -a PATTERN
PATTERN=("foo" "bar" "xyz")
OUT=("foo.txt" "bar.txt" "xyz.txt")
START_FD=5

parse() {
        l=$1;
        n=$START_FD
        for ((j=0;j<${#PATTERN[@]};j++)) ; do
                [[ "$l" =~ "${PATTERN[j]}" ]] && echo "$l" 1>&$n
                n=$((n+1))
        done
}

n=$START_FD
for ((j=0;j<${#OUT[@]};j++)) ; do
        eval 'exec '$n'> "${OUT[j]}"'
        n=$((n+1))
done
for i; do
        while read l ; do
                parse "$l"
        done < "$i"
done

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

Да оно кажется, что сложно, там просто навороченно для унификации и скорости: количество паттернов незахоркожено, выходные файлы открываются один раз, а потом только дозапись идёт в дескрипторы.

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

Покажи плз в man grep, где можно так сделать

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

Easy:

Маленькое но - у ТСа всё-таки в оригинале очистка файлов перед первым найденным.

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

Perl

perl -ne 'm/(foo|bar|xyz)/ && do { open(my $fh,">>$1.txt"); print $fh $_ }' file.txt
perl -ne 'BEGIN { open ($fh{$_}, ">$_.txt") for(qw/foo bar xyz/); } /(foo|bar|xyz)/ && print {$fh{$1}} $_ ' file.txt
pru-mike ★★
()
Ответ на: комментарий от rusya_rr

Потерей времени. Биг дата.

Башем бигдату ? Странно.

bryak ★★★★
()
27 июня 2017 г.
Ответ на: Perl от pru-mike

Спасибо!

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

print >>

Достаточно > , awk не shell, файл не закрывает, так что следующее срабатывание шаблона не обнулит файл.

futurama ★★★★★
()
19 февраля 2018 г.
Ответ на: комментарий от beastie

Продолжая тему.

А как сделать то же самое, если я не знаю, что будет в поле, но хочу продолжать складывать в файл с именем равным значению поля ? Спасибо.

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

Спасибо, работает, надо еще чуть допилить (см выше) Мне каким-то образом надо впилить еще кое-какие операции в bash до сохранения в файл.

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

Переспрошу по-другому. Мне нужно напечатать уникальные значения из всех значений одного столбца в файл с именем равным значению другого столбца.

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

Нашел, как отуникалить столбец по условию.

awk -F';' '$2=="bbb" {values[$1]++} END {for (value in values) { print value}}' text.txt
Как бы скрестить теперь эти два варианта?

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