Эффективный метод grep для сопоставления двух атомов? - PullRequest
3 голосов
/ 03 декабря 2008

Я ищу способ grep для нескольких атомов, например. "фу" и "бар". Я знаю, что могу использовать
grep 'foo' file | grep 'bar'
чтобы получить их обоих, но мне было интересно, если есть более эффективный способ. Кажется, что любой гугл бросает результаты только для поиска «или», а не «и».

Ответы [ 3 ]

5 голосов
/ 03 декабря 2008

Я сомневаюсь, что вы получите более эффективный способ, чем тот, который вы выбрали. Учитывая, что исполняемый файл grep уже будет отображен в память при запуске второй копии, и что у вас нет возврата в регулярном выражении (в отличие от egrep 'foo.*bar|bar.*foo' очевидного решения), я думаю, что у вас есть быстрый, как вы собираетесь получить.

Вот несколько примеров времени, чтобы проиллюстрировать это:

allan@allan-desktop:~$ time egrep 'foo.*bar|bar.*foo' foobar | wc -l
2000
real 0m0.006s
user 0m0.004s
sys  0m0.004s

allan@allan-desktop:~$ time fgrep 'foo' foobar | fgrep 'bar' | wc -l
2000
real 0m0.039s
user 0m0.000s
sys  0m0.000s

allan@allan-desktop:~$ time egrep 'foo.*bar|bar.*foo' foobar | wc -l
2000
real 0m0.006s
user 0m0.004s
sys  0m0.008s

allan@allan-desktop:~$ time fgrep 'foo' foobar | fgrep 'bar' | wc -l
2000
real 0m0.005s
user 0m0.004s
sys  0m0.004s

Из этого предположительно небольшого примера конвейерная версия требует меньше системного и пользовательского процессорного времени и, следовательно, более эффективна.

Входной файл состоит из 1000 копий:

foo-bar
bar-dgfjhdgjhdgdfgdjghdjghdfg-foo

чтобы вы могли запускать свои собственные тесты.

Это тот же тест с 100 000 строк ввода - вы можете видеть, что метод опроса более эффективен:

allan@allan-desktop:~$ time egrep 'foo.*bar|bar.*foo' foobar | wc -l
    100000
    real 0m0.135s
    user 0m0.136s
    sys  0m0.012s
allan@allan-desktop:~$ time fgrep 'foo' foobar | fgrep 'bar' | wc -l
    100000
    real 0m0.034s
    user 0m0.048s
    sys  0m0.012s
allan@allan-desktop:~$ time egrep 'foo.*bar|bar.*foo' foobar | wc -l
    100000
    real 0m0.151s
    user 0m0.144s
    sys  0m0.000s
allan@allan-desktop:~$ time fgrep 'foo' foobar | fgrep 'bar' | wc -l
    100000
    real 0m0.046s
    user 0m0.044s
    sys  0m0.012s
3 голосов
/ 03 декабря 2008
egrep '(foo.*bar|bar.*foo)'
# or
grep -E '(foo.*bar|bar.*foo)'
1 голос
/ 03 декабря 2008

Это может быть эффективным. :) Загрузка grep снова, вероятно, бесплатна из-за кэширования на уровне файловой системы. И, предполагая, что число попаданий мало (по сравнению с количеством строк ввода), и большинство строк, содержащих 'foo', тоже будут попаданиями для 'bar', второй экземпляр grep не мне многое нужно сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...