Sed/Awk сохранить текст между шаблонами, если содержит строку

У меня проблема с почтой. Мне нужно получить все сообщения от 2 человек:somebody1@domain.com а также person@domain.com,

file:

From: somebody1@domain.com
to: person@domain.com
<body of the message1>

From: somebody2@domain.com
to: person@domain.com
<body of the message1>

From: somebody1@domain.com
to: person@domain.com
<body of the message1>

From: somebody3@domain.com
to: person@domain.com
<body of the message1>

From: somebody5@domain.com
to: person@domain.com
<body of the message1>

Я пытался использовать следующее sed:

sed -n "/From: [Ss]omebody1/,/From: /p" inputfile > test.txt

В результате я получил все письма от test.txt файл.

Вопрос в том, какой должна быть структура sed получать только письма между кем-то1 и человеком?

2 ответа

С sed:

sed -n '/^From: somebody1@domain.com/{h;n;/^to: person@domain.com/{H;g;p;:x;n;p;s/.//;tx}}' file

  • /^From: somebody1@domain.com/: первый поиск From: адрес электронной почты
    • h; сохранить эту строку в пространстве удержания.
    • n; загрузить следующую строку (to: линия).
  • /^to: person@domain.com/: поиск to: адрес электронной почты
    • H; добавить эту строку в пространство удержания.
    • g; скопируйте пространство удержания в пространство шаблона.
    • p; распечатать шаблон пространства.
    • :x; установить ярлык с именем x,
    • n; загрузить следующую строку (тело письма)
    • p; напечатайте эту строку.
    • s/.// сделать замену в этой строке (просто заменить один символ)...
    • tx... что t Команда может проверить успешность этой замены (когда строка не пустая, как в конце тела письма). Если да, вернитесь к метке x и повторять, пока не появится пустая строка, если не перейти к концу скрипта.

Выход:

From: somebody1@domain.com
to: person@domain.com
<body of the message1>

From: somebody1@domain.com
to: person@domain.com
<body of the message1>

With awk:

awk '/From: [Ss]omebody1/{flag=1;next} \
  /to\: person1/ {if (flag>0) {flag=2; print; next} else {flag=0; next}} \
 /From/{flag=0} {if (flag==2){print NR,flag, $0}} ' input.txt 
  • /From: [Ss]omebody1/{flag=1;next} \ Put a flag variable to 1 on match and skip the line.
  • /to\: person1/ If the flag is 1 update it to 2 else reset it to 0.
  • /From/{flag=0} On match it reset the flag value.
  • {if (flag==2){print NR, $0}} if flag is 2 it will print the linenumber and the line.

Изменить значение person1 to have different matches.

Input file used

From: somebody1@domain.com
to: person2@domain.com
<body of the message1>

From: somebody2@domain.com
to: person1@domain.com
<body of the message2>

From: somebody1@domain.com
to: person1@domain.com
<body of the message3>

From: somebody1@domain.com
to: person1@domain.com
<body of the message4>

From: somebody3@domain.com
to: person@domain.com
<body of the message5>
Другие вопросы по тегам