Bash grep newline

[ Редакционная вставка: Возможный дубликат того же плаката более ранний вопрос?]

Привет, мне нужно извлечь из файла:

first
second
third

используя команду grep, следующую строку:

second
third

Как должна выглядеть команда grep?

Ответ 1

Вместо grep вы можете использовать pcregrep, который поддерживает многострочные шаблоны

pcregrep -M 'second\nthird' file

-M позволяет шаблону соответствовать нескольким строкам.

Ответ 2

Ваш аннотация вопроса bash grep newline "означает, что вы хотите совместить последовательность second\nthird символов, то есть что-то, содержащее в ней новую строку.

Так как grep работает на "строках", и эти две разные строки, вы не сможете сопоставить их таким образом.

Итак, я бы разделил его на несколько задач:

  • вы сопоставляете строку, содержащую "вторую", и выводите строку, которая соответствует, и следующую строку:

    grep -A 1 "second" testfile
    
  • вы переводите каждую другую строку новой строки в последовательность, которая не будет присутствовать во входе. Я думаю, что самый простой способ сделать это - использовать perl:

    perl -npe '$x=1-$x; s/\n/##UnUsedSequence##/ if $x;'
    
  • вы выполняете grep в этих строках, на этот раз, ища строку ##UnUsedSequence##third:

    grep "##UnUsedSequence##third"
    
  • вы разворачиваете неиспользуемые последовательности обратно в новые строки, sed может быть самым простым:

    sed -e 's/##UnUsedSequence##/\n'
    

Итак, получившаяся команда pipe, чтобы сделать то, что вы хотите, будет выглядеть так:

grep -A 1 "second" testfile | perl -npe '$x=1-$x; s/\n/##UnUsedSequence##/ if $x;' | grep "##UnUsedSequence##third" | sed -e 's/##UnUsedSequence##/\n/'

Не самый элегантный на сегодняшний день, но должен работать. Мне любопытно узнать о лучших подходах, хотя - должно быть что-то.

Ответ 3

Я не думаю, что grep - это способ сделать это.

Если вы просто хотите удалить первую строку из любого файла (чтобы обобщить ваш вопрос), я бы использовал sed.

sed '1d' INPUT_FILE_NAME

Это приведет к отправке содержимого файла в стандартный вывод с удалением первой строки.

Затем вы можете перенаправить стандартный вывод в другой файл, чтобы получить результаты.

sed '1d' INPUT_FILE_NAME > OUTPUT_FILE_NAME

Это должно сделать это.

Если вам нужно использовать grep и просто не хотите отображать строку с первой на ней, попробуйте следующее:

grep -v first INPUT_FILE_NAME 

Передавая переключатель -v, вы сообщаете grep, чтобы показать вам все , но выражение, которое вы передаете. По сути, покажите мне все, кроме строк с первым в них.

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

Чтобы шунтировать результаты в новый файл, попробуйте следующее:

grep -v first INPUT_FILE_NAME > OUTPUT_FILE_NAME

Надеюсь, что это поможет.

Ответ 4

Я действительно не понимаю, что вы хотите совместить. Я бы не использовал grep, но одно из следующего:

tail -2 file         # to get last two lines
head -n +2 file      # to get all but first line
sed -e '2,3p;d' file # to get lines from second to third

(не уверен, насколько это стандартно, он отлично работает в GNU-инструментах)

Ответ 5

Линия? Или строки?

Try

grep -E -e '(second|third)' filename

Изменить: grep ориентирован на линию. вам придется использовать Perl, sed или awk для выполнения соответствия шаблону по строкам.

BTW -E сообщает grep, что регулярное выражение расширено RE.

Ответ 6

Значит, вы просто не хотите, чтобы строка содержала "первый"? -v инвертирует результаты grep.

$ echo -e "first\nsecond\nthird\n" | grep -v first
second
third

Ответ 7

grep -A1 "second" | grep -B1 "third" работает красиво, и если у вас несколько совпадений, он даже избавится от разделителя оригинала - match

Ответ 8

grep -E '(second|third)' /path/to/file
egrep -w 'second|third' /path/to/file

Ответ 9

вы можете использовать

$ grep -1 third filename

это будет печатать строку с совпадением и одну строку до и после. Поскольку "третий" находится в последней строке, вы получаете последние две строки.

Ответ 10

Мне нравится notnoop answer, но на основе AndrewY answer (что лучше для тех, у кого нет pcregrep, но слишком сложно), вы можете просто сделать:

RESULT=`grep -A1 -s -m1 '^\s*second\s*$' file | grep -s -B1 -m1 '^\s*third\s*$'`

Ответ 11

grep -v '^first' filename

Если флаг -v инвертирует соответствие.