Я пытаюсь использовать, grep
чтобы показать только строки, содержащие одно из двух слов, если только одно из них появляется в строке, но не если они находятся в одной строке.
Пока я пытался, grep pattern1 | grep pattern2 | ...
но не получил ожидаемого результата.
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) Что, если одно из слов / шаблонов появляется более одного раза в строке (а другое не появляется)? Это эквивалентно тому, что слово появляется один раз, или оно считается как несколько вхождений?Ответы:
Инструмент, отличный
grep
от пути.Например, используя perl, команда будет:
perl -ne
выполняет команду, заданную для каждой строки стандартного ввода, которая в этом случае печатает строку, если она соответствует/pattern1/ xor /pattern2/
, или другими словами, соответствует одному шаблону, но не другому (исключающему или).Это работает для шаблона в любом порядке и должно иметь лучшую производительность, чем множественные вызовы
grep
, а также меньше печатать.Или, еще короче, с awk:
или для версий awk, которые не имеют
xor
:источник
xor
доступен только в GNU Awk?/pattern1/+/pattern2/==1
irxor
отсутствует.\b
) в самих моделях, то есть\bword\b
.С помощью GNU
grep
вы можете передать оба слова,grep
а затем удалить строки, содержащие оба шаблона.источник
Попробуй с
egrep
источник
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- предпочитаюgrep -E
-f
и-e
опции, хотя старыеegrep
иfgrep
будут поддерживаться некоторое время.grep
(который поддерживает-F
,-E
,-e
, ,-f
как POSIX требует) в/usr/xpg4/bin
. Утилиты в/bin
устарели.С
grep
реализациями, которые поддерживают Perl-подобные регулярные выражения (например,pcregrep
или GNU, или ast-opengrep -P
), вы можете сделать это за одинgrep
вызов:То есть найдите линии, которые соответствуют,
pat1
но не соответствуютpat2
, илиpat2
нетpat1
.(?=...)
и(?!...)
соответственно смотрят в будущее и смотрят в будущее операторы. Технически, вышесказанное ищет начало субъекта (^
), если за ним следует,.*pat1
а не следует.*pat2
, или то же самое сpat1
и вpat2
обратном порядке.Это неоптимально для строк, которые содержат оба шаблона, так как их потом будут искать дважды. Вместо этого вы можете использовать более продвинутые операторы Perl, такие как:
(?(1)yespattern|nopattern)
совпадает с совпадающейyespattern
группой1
st st (пустой()
сверху), и вnopattern
противном случае. Если это()
соответствует, это означает, чтоpat1
не соответствует, поэтому мы ищемpat2
(позитивный взгляд вперед), и мы ищем неpat2
иначе (негативный взгляд вперед).С помощью
sed
вы можете написать это:источник
grep: the -P option only supports a single pattern
, по крайней мере, в каждой системе, к которой у меня есть доступ. +1 за ваше второе решение, хотя.grep
.pcregrep
и у ast-open grep такой проблемы нет. Я заменил-e
множитель оператором чередования RE, поэтомуgrep
теперь он должен работать и с GNU .В логических терминах вы ищете A xor B, который можно записать как
(А, а не В)
или
(Б а не А)
Учитывая, что в вашем вопросе не упоминается, что вы обеспокоены порядком вывода, пока отображаются соответствующие строки, логическое расширение A xor B чертовски просто в grep:
источник
sort | uniq
.Для следующего примера:
Это может быть сделано исключительно с
grep -E
,uniq
иwc
.Если
grep
скомпилировано с регулярными выражениями Perl, вы можете сопоставить последнее вхождение, вместо того, чтобы передаватьuniq
:Выведите результат:
Однострочник:
Если вы не хотите жестко кодировать шаблон, его сборка с переменным набором элементов может быть автоматизирована с помощью функции.
Это также может быть сделано изначально в Bash как функция без конвейеров или дополнительных процессов, но будет более сложным и, вероятно, выходит за рамки вашего вопроса.
источник
Big apple\n
иpear-shaped\n
, то выход должен содержать обе эти строки. Ваше решение получит счет 2; длинная версия будет сообщать «оба слова совпадают» (что является ответом на неправильный вопрос), а короткая версия вообще ничего не говорит. (3) Предложение: использование-o
здесь - очень плохая идея, потому что оно скрывает строки, содержащие совпадения, поэтому вы не можете видеть, когда оба слова появляются на одной строке. … (Продолжение)uniq
/sort -u
и необычного регулярного выражения Perl для сопоставления только с последним вхождением в каждой строке на самом деле не дает полезного ответа на этот вопрос. Но даже если бы они это сделали, это все равно было бы плохим ответом, потому что вы не объясняете, как они способствуют ответу на вопрос. (См . Ответ Стефана Шазеласа для примера хорошего объяснения.)