bash grep newline - PullRequest
       17

bash grep newline

11 голосов
/ 04 августа 2009

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

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

first
second
third

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

second
third

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

Ответы [ 11 ]

20 голосов
/ 04 августа 2009

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

pcregrep -M 'second\nthird' file

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

8 голосов
/ 04 августа 2009

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

Поскольку grep работает с "линиями", а эти две строки разные, вы не сможете сопоставить его таким образом.

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

  1. вы соответствуете строке, содержащей «second», и выводите строку, которая соответствует, и следующую строку:

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

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

    grep "##UnUsedSequence##third"
    
  4. вы разворачиваете неиспользованные последовательности обратно в новые строки, 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 голосов
/ 04 августа 2009

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

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

sed '1d' INPUT_FILE_NAME

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

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

sed '1d' INPUT_FILE_NAME > OUTPUT_FILE_NAME

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

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

grep -v first INPUT_FILE_NAME 

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

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

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

grep -v first INPUT_FILE_NAME > OUTPUT_FILE_NAME

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

2 голосов
/ 04 августа 2009

Я не очень понимаю, что вы хотите соответствовать. Я бы не использовал 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)

1 голос
/ 25 февраля 2014

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

1 голос
/ 04 августа 2009

То есть вы просто не хотите, чтобы строка содержала «first»? -v инвертирует результаты grep.

$ echo -e "first\nsecond\nthird\n" | grep -v first
second
third
1 голос
/ 04 августа 2009

Line? Или линии?

Попробуйте

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

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

Кстати, - скажите grep, что регулярное выражение расширено RE.

0 голосов
/ 01 мая 2013
grep -v '^first' filename

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

0 голосов
/ 16 августа 2012

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

RESULT=`grep -A1 -s -m1 '^\s*second\s*$' file | grep -s -B1 -m1 '^\s*third\s*$'`
0 голосов
/ 18 апреля 2012

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

$ grep -1 third filename

это напечатает строку с соответствием и одну строку до и после. Так как «третий» находится в последней строке, вы получаете последние две строки.

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