On 2008-06-20 at 14:48 +0200, Marten Lehmann wrote:
> I read this, but I don't understand where is the difference wether \n is
> expanded by exim to a newline (without using \N or using \\n) or using
> \N so PCRE transforms \n to a newline.
In this case, not much. Just be sure to also use \$ instead of $ to
anchor the end of the regexp, etc etc. \N removes the need for one
layer of backslashes so is generally less error-prone.
> > Try:
> > ${sg{$spam_report}{\N^.*\n\s*X-purgate-ID: (.*?)\n.*$\N}{\$1}}
>
> Thanks, this works. But it only works, because I know the exact format
> of $spam_report. How can I tell ${sg{}} to include \n to the matching
> characters of .*? I think in Perl this was done by the modifier /s.
Embed the modifier at the start of the regexp with (?s) -- see manual
pages perlre(1) (for Perl's documentation) or pcrepattern(3) (comes with
later versions of pcre). The latter describes this under "INTERNAL
OPTION SETTING".
> Is there any way on exim (besides to embed Perl) to extract a value like
>
> $id = $1 if $spam_report =~ /(^|\n)X-purgate-ID: (.*?)(\n|$)/s ?
Again, adding the \s* at the start so that X-purgate-ID: doesn't need to
be at the beginning of the line:
${sg{$spam_report}{\N(?s)^(?:.*\n|)\s*X-purgate-ID:\s+([^\n]+)(?:|\n.*)$\N}{\$1}}
The main reason it's longer is because sg is short for Perl's s///g so
you need to handle the lines which _don't_ match and don't get away with
conditional setting.
That's the one long regexp approach. The closest you'll get to a
conditional is to use map-filter on lists generated by using newline as
a separator:
${map\
{<\n ${filter {<\n $spam_report}{match{$item}{\N^X-purgate-ID:\N}}}}\
{${sg{$item}{\N^[^:]+:\s*(.*)\N}{\$1}}}\
}
The straight regexp is probably faster, since you enter the regexp
engine just once.
Regards,
-Phil