Как извлечь текст между двумя словами в unix?

I
я
используя
основной
sed
выражение: -

sed -n "am/,/sed/p" 

чтобы получить текст между "am" и "sed", который будет выводить "am\n используя \n basic\n sed". Но моя реальная проблема заключается в том, что строка будет: -

I
я
используя
основной
grep

выражение.

Я применил вышеприведенное sed в этом предложении то он дал "am\n, используя \n basic\n grep\n выражение" который он не должен давать. Как отказаться от если не будет соответствия?

Любые предложения?

Ответы

Ответ 1

Команда в вопросе (sed -n "/am/,/sed/p", обратите внимание на добавленную косую черту) означает:

  • Найдите строку, содержащую строку am
  • и напечатать (p) до появления строки, содержащей sed

Поэтому он печатает:

I am using basic grep expression

поскольку он содержит am. Если вы добавите еще несколько строк, они также будут напечатаны до тех пор, пока не появится строка, содержащая sed.

например:.

echo -e 'I am using basic grep expression.\nOne more line\nOne with sed\nOne without' | sed -n "/am/,/sed/p"

приводит к:

I am using basic grep expression.
One more line
One with sed

Я думаю - что вы хотите сделать, это что-то вроде этого:

sed -n "s/.*\(am.*sed\).*/\1/p"

Пример:

echo 'I am using basic grep expression.' | sed -n "s/.*\(am.*sed\).*/\1/p"

echo 'I am using basic sed expression.' | sed -n "s/.*\(am.*sed\).*/\1/p"
sed -n "s/.*\(am.*sed\).*/\1/p"

Ответ 2

Вам нужно использовать несколько другую команду sed, например:

sed -n '/am/{:a; /am/x; $!N; /sed/!{$!ba;}; /sed/{s/\n/ /gp;}}' file

Чтобы напечатать ТОЛЬКО строки, содержащие текст am и sed, натянутый на несколько строк.

Ответ 3

При использовании SED это может работать, но это довольно подавляющий синтаксис... если вам нужно обрезать часть многострочного (\n) текста, вы можете попробовать более простой способ с помощью grep:

cat multi_line.txt | grep -oP '(?s)(?<=START phrase).*(?=END phrase)'

Например, я считаю это самым легким способом захватить описание perlce changelist (без остальной информации CL):

p4 describe {CL NUMBER} | grep -oP '(?s).*(?=Affected files)'

Примечание. Вы можете играть с <= и > =, чтобы включать или не включать в себя начальные/конечные фразы на выходе.