Как выполнить grep -v -e 'expr1' и grep -e 'expr2' одной командой?

С помощью GNU sed вы можете:

sed -E 's/(\|[^ |]+) /\1| /
        s/(([^|]* )?([^|]*))\|(([^ ]*)(.*))/\1\6\n\2\4/
        /\n/P;D' <infile

... который печатает ...

TMPRSS2 AADAT Sample1
pp9284 AADAT Sample1
ERG    TMPRSS2 Sample2
ERG    pp9284 Sample2
TMPRSS2 ETV1 Sample3
pp9284 ETV1 Sample3
PDE4A   MIA Sample4
PDE4A   MIA-RAB4B Sample4
PDE4A   RAB4B Sample4
PDE4A   RAB4B-EGLN2 Sample4
PDE4A   EGLN2 Sample4

Он работает путем разделения и печать с последующим частичным удалением содержимого строки на дополнительных \ n символах ewline. Команда P P печатает только до первой появившейся \ n строки в пространстве шаблонов, поэтому вы можете довольно легко распечатать только часть своего буфера редактирования как тебе нравится.

В этом случае для каждого разделенного на конвейер раздела, не содержащего пробелов, sed помещает все биты на обоих концах буфера редактирования дважды. sed вставляет крайний левый и крайний правый концы слева и справа от самой левой секции, разделенной на каналы, и следует этой последовательности с помощью \ n ewline, затем он помещает те же выборки в любой конец всех разделенных трубопроводами секций, которые остаются с правой стороны его вставленной \ n прямой линии. Итак, sed может P ринтировать только бит слева, если в пространстве шаблонов вообще есть \ n ewline, тогда D выберите только до первой встречающейся \ n строки ewline в пространстве шаблонов и повторите попытку.

Самая первая подстановка происходит только один раз - она ​​просто добавляет канал к концу секций, разделенных трубкой, так что всегда будет канал для разделения - даже для последнего случая.В остальное время sed выполняет одно s /// ubstitution, P записывает первую строку в пространстве шаблонов, затем D избирает то же самое. Когда он больше не может этого делать, он D удаляет все пространства шаблонов и автоматически вставляет следующую строку ввода.

Чтобы сделать то же самое, можно написать POSIX BRE:

sed '   s/\(|[^ |]\{1,\}\) /\1| /
        s/^\(\( *[^ |]*  *\)*\([^ |]*\)\)|\(\([^ ]*\)\(.*\)\)/\1\6\
\2\4/;   /\n/P;D' <infile
2
17.08.2018, 12:52
2 ответа

Вы не можете комбинировать обратное и прямое сопоставление в одном grepвызове

Вы можете сделать это с помощьюsed:

sed -e '/^www\./d' -e '/\//d' -e '/^[^.]*\.[^.]*$/!d'./*.txt

Или awk(, который, в отличие от sed, сможет напечатать имя соответствующего файла, напримерgrep):

awk -F. 'NF == 2 && !/^www\./ && !/\// {print FILENAME": "$0}'./*.txt

Вы можете сделать это с помощью двух вызовов grep, если вы не хотите, чтобы имена файлов печатались:

cat./*.txt | grep '^[^.]*\.[^.]*$' | grep -v -e / -e '^www\.'

Здесь используется catдля подачи содержимого всех файлов на стандартный ввод, поэтому первый grepне печатает имена файлов. В некоторых grepреализациях есть grep -hпропуск вывода имен файлов, если файлов больше одного. В случае только одного имени файла grepвсе равно не печатает имя файла, и вы можете передать его на стандартный ввод с перенаправлениями:

<onefile.txt grep '^[^.]*\.[^.]*$' | grep -v -e / -e '^www\.'

Вы можете реализовать отрицание с помощью (?!...)негативного просмотра -опережающих операторов PCRE, если ваш grepподдерживает-P:

grep '^(?!www\.)(?!.*/)[^.]*\.[^.]*$'./*.txt

Но здесь вы могли бы сделать все это с -vс:

grep -v -e / -e '^www\.' -e '^[^.]*$' -e '\..*\.'

Это также исключает строки, не содержащие точки, и строки, содержащие более одной точки.

2
27.01.2020, 21:58

Передать первый результат grepво второй grep.

2
27.01.2020, 21:58

Теги

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