С grep, как я могу соответствовать шаблону и инвертировать, соответствуют другому шаблону?

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

agrep 'pattern1;pattern2'

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

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

С ast grep:

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

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

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

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

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

awk '/pattern1/ && /pattern2/'

С sed:

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

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

10
17.10.2013, 16:52
3 ответа

Если у Вас есть GNU grep, можно использовать регулярные выражения Perl, которые имеют конструкцию отрицания.

grep -A1 -P '^(?!.*ignore me).*needle'

Если у Вас нет GNU grep, можно эмулировать перед/после того, как опциями контекста в awk.

awk -v after=3 -v before=2 '
/needle/ && !/ignore me/ {
    for (i in h) {
        print h[i];
        delete h[i];
    }
    until = NR + after;
}
{
    if (NR <= until) print $0; else h[NR] = $0;
    delete h[NR-before];
}
END {exit !until}
'
8
27.01.2020, 20:01

Вы, кажется, используете GNU . С GNU grep, Вы могли передать в --perl-regex флаг, чтобы активировать PCRE и затем предоставить отрицательное предварительное утверждение, пример ниже

grep --after-context=1 \
--perl-regex '^(?:(?!ignore me).)*needle(?:(?!ignore me).)*$' file.txt
four needle
five

Знаменитое главное здесь - это (?:(?!STRING).)* к STRING как [^CHAR]* к CHAR

8
27.01.2020, 20:01
  • 1
    @1_CR... Сэр.. это является потрясающим.. :P что-то smiler к ack –  Rahul Patil 17.10.2013, 18:40
  • 2
    @RahulPatil. :-), да GNU grep настолько хорош. –  iruvar 17.10.2013, 18:49
  • 3
    Это не совсем, что я хочу. Я хочу, чтобы это работало, игнорируют ли "меня", прежде или после "иглы". –  Flimm 17.10.2013, 18:57
  • 4
    @RahulPatil, спасибо, я зафиксировал его в последней версии –  iruvar 17.10.2013, 19:17
  • 5
    Очень полезный. Особенно в случае grep с контекстом, где Вы хотите исключить тесно согласующие отрезки длинной линии, но без определенной части шаблона. Близко к исходному вопросу, но не совсем тому же. –  gaoithe 31.03.2016, 17:01

Я предложил бы использовать awk вместо этого, поскольку он обрабатывает многострочный IO лучше. Любой 1) Канал результаты к GNU awk с --\n как разделитель записей, или 2) Делают все соответствие в awk.

Опция 1

<file grep -A1 needle | awk '!/ignore me/' RS='--\n' ORS='--\n'

Вывод:

four needle                                                                                  
five
--

Отметьте, эта опция ищет целую запись ignore me, набор FS=1 и соответствие против $1 только выдерживать сравнение с первой строкой.

Опция 2

<file awk 'a-- > 0; $0 ~ re1 && $0 !~ re2 { print $0; a=after }' re1=needle re2='ignore me' after=1
2
27.01.2020, 20:01
  • 1
    , там несколько ignore me в файле затем, awk не –  Rahul Patil 17.10.2013, 19:22
  • 2
    @RahulPatil: Вы могли перефразировать или добавить больше детали к своему вопросу? Я не понимаю то, что Вы спрашиваете. –  Thor 17.10.2013, 22:05
  • 3
    @Thos тестирует Ваш пример с этим входным файлом paste.ubuntu.com/6252860 –  Rahul Patil 17.10.2013, 22:41
  • 4
    @RahulPatil: Я вижу то, что Вы имеете в виду теперь, Опция 1 принимает это a --\n разделитель между каждой подобранной группой, которая не является там, если группы смежны друг с другом. То, как смежные группы должны быть обработаны, является определенным для задачи, таким образом, это не обязательно неправильно. Опция 2 не зависит от разделителя и не затронута. –  Thor 17.10.2013, 23:59

Теги

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