2015-09-24 2 views
4

У меня есть сценарий, написанный в bash, с одной командой grep, которую мне нужно изменить.bash grep regexp - исключая subpattern

Вообще у меня есть две модели: а & Б. Существует текстовый файл, который может содержать строки со всеми возможными комбинациями этих моделей, то есть: «xxxAxxx», «xxxBxxx», «xxxAxxxBxxx», «XXXXXX», где «x» - любые символы.

Мне нужно сопоставить ВСЕ строки APART из тех, которые содержат ТОЛЬКО "A".

На данный момент это делается с помощью «grep -v (A)», но это ложный трек, так как это исключает также строки с «xxxAxxxBxxx» - которые подходят для меня. Вот почему он нуждается в модификации. :)

Сложная часть состоит в том, что этот grep лежит посреди команды «multiply-piped» со многими другими greps, seds и awks внутри. Таким образом, формирование более разумного шаблона было бы лучшим решением. Другие могли бы потребовать много дополнительной работы по изменению других команд там и даже повлиять на другие части кода.

Таким образом, возникает вопрос: существует ли возможность сопоставить шаблон и исключить подшаблон в одном grep, но разрешить им отображаться как в одной строке?

Пример: Файл содержит эти строки:

fooTHISfoo 
fooTHISfooTHATfoo 
fooTHATfoo 
foofoo 

и мне нужно, чтобы соответствовать

fooTHISfooTHATfoo 
fooTHATfoo 
foofoo 

линии с "ЭТА" не допускается.

ответ

3

Вы можете использовать эту команду AWK:

awk '!(/THIS/ && !/THAT/)' file 
fooTHISfooTHATfoo 
fooTHATfoo 
foofoo 

Или, перевернув логическое выражение:

awk '!/THIS/ || /THAT/' file 
fooTHISfooTHATfoo 
fooTHATfoo 
foofoo 
+1

На самом деле я не заметил, что мой случай может быть написан как логическое выражение ... Решение отлично работало, спасибо вам большое. – ptr92zet

1

Tricky для grep в одиночку. Тем не менее, заменить, что с вызовом AWK: Фильтр из строки с «A», если не является «B»

echo "xxxAxxx 
xxxBxxx 
xxxAxxxBxxx 
xxxBxxxAxxx 
xxxxxx" | awk '!/A/ || /B/' 
xxxBxxx 
xxxAxxxBxxx 
xxxBxxxAxxx 
xxxxxx 
+0

Другой, более длинный способ написать это: 'awk '/ B/{print; next}/A/{next} 1 {print} '' –

2

Вы хотите, чтобы соответствовать строки, содержащие B, или не содержат A , Эквивалентно, чтобы удалить строки, содержащие A, а не B. Вы можете сделать это в СЕПГ:

sed -e '/A/{;/B/!d}' 

Или в данном конкретном случае:

sed '/THIS/{/THAT/!d}' file 
+0

Хорошая старая' sed' выглядит как лучшая альтернатива в этой теме! :) Плюс один! – hek2mgl

1

grep решение. Использует perl regexp (-P) для Lookaheads (посмотрите, если нет, некоторые пояснения here).

grep -Pv '^((?!THAT).)*THIS((?!THAT).)*$' file 
+0

В конце концов я закончил awk, но я тоже проверю это, так что спасибо вам! :) – ptr92zet