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>