Как выполнить grep с несколькими И шаблонами?

Чтение вперед:

В системах на 32 бита:

blockdev --setra 8388607 /dev/sda

В системах на 64 бита:

blockdev --setra 4294967295 /dev/sda

Запись позади кэша:

echo 100 > /proc/sys/vm/dirty_ratio

Это будет использовать до 100% Вашей свободной памяти как кэш записи.

Или можно полностью выложиться и использовать tmpfs. Это только релевантно, если у Вас есть RAM достаточно. Вставьте это /etc/fstab. Замена 100G с суммой физической RAM.

tmpfs /mnt/tmpfs tmpfs size=100G,rw,nosuid,nodev 0 0

Затем:

mkdir /mnt/tmpfs; mount -a

Затем используйте/mnt/tmpfs.

88
13.11.2012, 23:01
8 ответов

agrep может сделать это с этим синтаксисом:

agrep 'pattern1;pattern2'

С GNU grep, при создании с поддержкой PCRE можно сделать:

grep -P '^(?=.*pattern1)(?=.*pattern2)'

С ast grep:

grep -X '.*pattern1.*&.*pattern2.*'

(добавление .*s как <x>&<y> строки соответствий то соответствие оба <x> и <y> точно, a&b никогда не соответствовал бы, поскольку нет такой строки, которая может быть обоими a и b одновременно).

Если шаблоны не накладываются, можно также смочь сделать:

grep -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'

Лучший портативный путь, вероятно, с awk как уже упомянуто:

awk '/pattern1/ && /pattern2/'

С sed:

sed -e '/pattern1/!d' -e '/pattern2/!d'

Остерегайтесь этого всего, у этого будет другой синтаксис регулярного выражения.

80
27.01.2020, 19:30
  • 1
    agrep синтаксис не работает на меня..., в какой версии он был представлен? –  Raman 06.09.2016, 01:15
  • 2
    @Raman 2.04, с 1992 уже имел его. У меня нет причины полагать, что это не было там от запуска. Более новый (после 1992) версии agrep может быть найден включенным с glimpse/webglimpse. Возможно у Вас есть другая реализация. У меня была ошибка для ast-grep версии, хотя, опция для увеличенного regexps -X, нет -A. –  Stéphane Chazelas 06.09.2016, 08:55
  • 3
    @StéphaneChazelas Благодарит, я имею agrep 0.8.0 на Fedora 23. Это, кажется, другое agrep чем тот Вы ссылаетесь. –  Raman 06.09.2016, 09:37
  • 4
    @Raman, Ваш походит на TRE agrep. @Yokai –  Stéphane Chazelas 06.09.2016, 10:01
  • 5
    @Techiee, или просто awk '/p1/ && /p2/ {n++}; END {print 0+n}' –  Stéphane Chazelas 28.06.2017, 23:23

Вы не указывали grep версию, это важно. Некоторые regexp механизмы позволяют нескольким соответствующим сгруппированному И использующий '&', но это - нестандартная и непортативная функция. Но, по крайней мере, GNU grep не поддерживает это.

OTOH можно просто заменить grep sed, awk, жемчугом, и т.д. (перечисленный в порядке увеличения веса). С awk команда была бы похожа

awk '/regexp1/ && /regexp2/ && /regexp3/ { print; }'

и это может быть создано, чтобы быть указанным в командной строке простым способом.

19
27.01.2020, 19:30
  • 1
    Просто помните это awk ERE's использования, например, эквивалент grep -E, в противоположность той плоскости BRE grep использование. –  jw013 10.11.2012, 11:42
  • 2
    awkregexes называют EREs, но на самом деле они являются немного особенными. Вот, вероятно, больше деталей, чем кто-либо заботится: wiki.alpinelinux.org/wiki/Regex –  dubiousjim 10.11.2012, 17:35
  • 3
    Спасибо, grep 2.7.3 (openSUSE). Я upvoted Вы, но я сохраню вопрос открытым некоторое время, возможно, существует некоторый прием для grep (не, что мне не нравится awk - просто знание больше лучше). –  greenoldman 10.11.2012, 17:42
  • 4
    , действие по умолчанию должно распечатать согласующий отрезок длинной линии так { print; } часть не действительно необходима или полезна здесь. –  tripleee 20.04.2017, 14:58

Если patterns содержит по одному шаблону в строке, вы можете сделать что-то вроде этого:

awk 'NR==FNR{a[$0];next}{for(i in a)if($0!~i)next}1' patterns -

Или это соответствует подстрокам вместо регулярных выражений:

awk 'NR==FNR{a[$0];next}{for(i in a)if(!index($0,i))next}1' patterns -

Чтобы вывести все строки, а не ни одной, в случае, если patterns пуст, замените NR==FNR на FILENAME==ARGV[1], или на ARGIND==1 в gawk.

Эти функции выводят строки STDIN, которые содержат каждую строку, указанную в качестве аргумента, как подстроку. ga означает grep all, а gai игнорирует регистр.

ga(){ awk 'FILENAME==ARGV[1]{a[$0];next}{for(i in a)if(!index($0,i))next}1' <(printf %s\\n "$@") -; }
gai(){ awk 'FILENAME==ARGV[1]{a[tolower($0)];next}{for(i in a)if(!index(tolower($0),i))next}1' <(printf %s\\n "$@") -; }
7
27.01.2020, 19:30

Это не очень хорошее решение, но демонстрирует несколько крутой "трюк"

function chained-grep {
    local pattern="$1"
    if [[ -z "$pattern" ]]; then
        cat
        return
    fi    

    shift
    grep -- "$pattern" | chained-grep "$@"
}

cat something | chained-grep all patterns must match order but matter dont
7
27.01.2020, 19:30

Чтобы найти все слова (или шаблоны ), вы можете запустить grepв цикле for. Основным преимуществом здесь является поиск по списку регулярных выражений .

Реальный пример:

# File 'search_all_regex_and_error_if_missing.sh'

find_list="\
^a+$ \
^b+$ \
^h+$ \
^d+$ \
"

for item in $find_list; do
   if grep -E "$item" file_to_search_within.txt
   then
       echo "$item found in file."
   else
       echo "Error: $item not found in file. Exiting!"
       exit 1
   fi
done

Теперь запустим этот файл:

hhhhhhhhhh
aaaaaaa
bbbbbbbbb
ababbabaabbaaa
ccccccc
dsfsdf
bbbb
cccdd
aa
caa
$./search_all_regex_and_error_if_missing.sh
aaaaaaa aa
^a+$ found in file.
bbbbbbbbb bbbb
^b+$ found in file.
hhhhhhhhhh
^h+$ found in file.
Error: ^d+$ not found in file. Exiting!
-2
27.01.2020, 19:30

Вот мое мнение, и это работает для слов в несколько строк:

Используйте find. -type fи столько же
-exec grep -q 'first_word' {} \;
и последнее ключевое слово с
-exec grep -l 'nth_word' {} \;

-qтихо / тихо
-lпоказывать файлы с совпадениями

Следующее возвращает список имен файлов со словами «кролик» и «дырка» в них:
find. -type f -exec grep -q 'rabbit' {} \; -exec grep -l 'hole' {} \;

3
27.01.2020, 19:30

ripgrep

Вот пример использованияrg:

rg -N '(?P<p1>.*pattern1.*)(?P<p2>.*pattern2.*)(?P<p3>.*pattern3.*)' file.txt

Это один из самых быстрых инструментов поиска, так как он построен на основе механизма регулярных выражений Rust , который использует конечные автоматы, SIMD и агрессивную литеральную оптимизацию для очень быстрого поиска.

См. также соответствующий запрос функции по адресу GH -875 .

1
27.01.2020, 19:30

для поиска в нескольких файлах наличия двух шаблонов в любом месте файла используйте

awk -v RS="" '/patern1/&&/patern2/{print FILENAME}' file1... filen
1
25.05.2021, 20:22

Теги

Похожие вопросы