How can I use SED or AWK to replace placeholders in a template file with variable content that contains special characters?
Solution 1
This is difficult in sed because in sed s/TMPHEADERS/"$HEADERS"/
, the value of the variable is substituted by the shell before the command reaches sed, so
characters like &\/
that appear in $HEADERS
have a special meaning in the replacement text. Sed does not have a variable lookup facility.
This task is fairly easy with awk. Pass the HEADERS
variable in the environment:
export HEADERS
</test/emailtemplate awk '
{gsub(/^TMPHEADERS$/, environ["HEADERS"]); print}
' > /test/output
or as an awk variable:
</test/emailtemplate awk -v HEADERS="$HEADERS" '
{gsub(/^TMPHEADERS$/, HEADERS); print}
' > /test/output
Solution 2
There are several possibilities:
sed You would have to escape every char in "$HEADERS" to make the sed call safe.
HEADERS_ESCAPED="$(echo "$HEADERS" | sed -n 's/./\\&/gp')"
# double-useless use of cat BTW
sed "s/TMPHEADERS/$HEADERS_ESCAPED/" /test/emailtemplate > /test/output
BTW: There is absolutely no reason to call sed once for every change:
sed -n -e s/X/"$X"/ -e s/Y/"$Y" -e s/Z/"$Z"/ -e p inputfile > outputfile
bash itself
while IFS= read -r line; do
line="${line/TMPDATE/"$TMPDATE"}"
# ...
line="${line/TMPHEADERS/"$HEADERS"}"
printf '%s\n' "$line"
done <inputfile >outputfile
Solution 3
I'm not sure I understand what you want to do. If you want to, for example, replace the string TMPHEADERS
with the long list of header info you posted, this Perl solution can do it:
perl -e 'open(A,"header"); ## open the header file
$h=join("",<A>); ## save its contents in a string
while(<>){ ## go through the input file
s/TMPHEADERS/$h/; ## replace
print ## print each line
}' template
The file template
is the template from your question and the file header
has the header lines you posted. The result is
Alert Report
Alert has triggered at TMPDATE
HEADERS
-------
From [email protected] Thu Apr 25 20:18:19 2013
Return-Path: <[email protected]>
Received: from nm30-vm0.bullet.mail.ne1.yahoo.com (nm30-vm0.bullet.mail.ne1.yahoo.com [98.138.11.36])
by serv.example.com (8.14.4/8.14.4) with ESMTP id r3Q3IJVV009411
for <[email protected]>; Thu, 25 Apr 2013 20:18:19 -0700
Received: from [108.108.108.108] by nm30.bullet.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:19 -0000
Received: from [98.138.87.11] by tm15.bullet.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:17 -0000
Received: from [127.0.0.1] by omp1001.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:17 -0000
X-Yahoo-Newman-Property: ymail-3
X-Yahoo-Newman-Id: [email protected]
Received: (qmail 29701 invoked by uid 65501); 26 Apr 2013 03:18:17 -0000
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s1024; t=1366946297; bh=yjMzVONHAyJxQob7tLNdIN2RpfGHWVw1Kb5Qr+enYF8=; h=X-YMail-OSG:Received:X-Rocket-MIMEInfo:X-Mailer:Message-ID:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=CQGilBx8NertE4j75dsfsdfs+IKRzIx5vlH5YdzqFLd4ThfEyMs11sdfsdfsdXsAH1yteACnwSER+QXJQ80BfLGbJnIWm+29I8A4geOPIHGKoOUCnPaD+/0bHfAps0JIcwEju8Tcvg4VDVWw=
DomainKey-Signature:a=rsa-sha1; q=dns; c=nofws;
s=s1024; d=yahoo.com;
h=X-YMail-OSG:Received:X-Rocket-MIMEInfo:X-Mailer:Message-ID:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type;
b=5TIRL55VM2J2lPLsX9iCE4sdlkfjlEM2245M6qzg1oGrnZd61ykL4xQSsc3cYNz95fwNy67aRRC89n6xcti28ee5rjmlK0MDIskSB5sKlv165mNjmzF1LNx6uFXalI8QGSwiQt2uWLYvI7RrTVeZFELDfFVZyqygEl5k=;
X-YMail-OSG: EDT4ym4VM1lVQMdtAQ5zqfE59jR1Mtip4vVL1fBzNxFdGvA
YjAJ3MXC1EusloknrsPx3drxzR1b4PFErK.UhdgWePhK7TTCHhhju4XP4i7x
76WASceqp77T5itvZmilv5UuICJw3BCEd0fdADctfBYhLNwoALxjp6cnJMmE
Z4dYVtlp5vUFqg1pHxqGOXqrtjeZffM4dMftnn.Q8LlVEkj3pZ6ZJV_kKFtj
vGEGS5PAW0tIHWPEqVERYzmDOfF5sVSQLayPi6EM_i1OE038434laijEWbH0
nZt1Vkg3syO0t1BaTLN4B1bXeS8cv3GlbLO4ot7zVwA3sH4UhsC5M6xiWNFU
3iroObJ5BObL99VO3ktvC4KzekAWJ_fE85TQJhQKj6Iolgb4xlWa2x414xuA
awO4pJI9grDjycUcmhmKwLZEt_.0OBLfSi5MSviaiCNMuU5qIdHm7VCGdORP
Mc68rDkpmJE9I9Z.QZfhH5cFxqqmpyIOMTs0iIBGYz5d9QHMWCuo-
Received: from [102.102.102.102] by web12341105.mail.ne1.yahoo.com via HTTP; Thu, 25 Apr 2013 20:18:17 PDT
X-Rocket-MIMEInfo: 002.001,VGVzdGluZyAxMjMgTGEgbGEgbGEBMAEBAQE-
X-Mailer: YahooMailWebService/0.8.141.536
Message-ID: <[email protected]>
Date: Thu, 25 Apr 2013 20:18:17 -0700 (PDT)
From: Test Account <[email protected]>
Reply-To: Test Account <[email protected]>
Subject: Test
To: "[email protected]" <[email protected]>
MIME-Version: 1.0
Content-Type: multipart/alternative; boundary="102743210-1541163991-1366946297=:49149"
SOURCE IP
---------
TMPSOURCEIP
You can extend this for two sets of headers as follows:
perl -e 'open(A,"header1");
$h1=join("",<A>);
open(B,"header2");
$h2=join("",<B>);
while(<>){
s/TMPHEADERS/$h1/;
s/TMPSOURCEIP/$h2/;
print
}' template
Solution 4
Using the m4
macro processor to replace TMPSOURCEIP
and TMPDATE
with things defined on the command line and TMPHEADERS
with whatever is in the file headers.txt
. The template is in template.txt
.
$ m4 -DTMPDATE="$(date)" -DTMPSOURCEIP="1.1.1.1" -DTMPHEADERS='include(headers.txt)' template.txt
Alert Report
Alert has triggered at Mon Sep 25 18:46:34 CEST 2017
HEADERS
-------
From [email protected] Thu Apr 25 20:18:19 2013
Return-Path: <[email protected]>
Received: from nm30-vm0.bullet.mail.ne1.yahoo.com (nm30-vm0.bullet.mail.ne1.yahoo.com [98.138.11.36])
by serv.example.com (8.14.4/8.14.4) with ESMTP id r3Q3IJVV009411
(etc.)
SOURCE IP
---------
1.1.1.1
If you already have the headers in a variable, you may obviously replace -DTMPHEADERS='include(headers.txt)'
with -DTMPHEADERS="$headers"
.
Related videos on Youtube
Mike B
Updated on September 18, 2022Comments
-
Mike B over 1 year
CentOS 6.3
I'm trying to get a small script to send an email containing a copy of email headers in the body (for the purpose of internal reporting).
The template file contains the following:
Alert Report Alert has triggered at TMPDATE HEADERS ------- TMPHEADERS SOURCE IP --------- TMPSOURCEIP
I want my script to find and replace the "TMP" place holders with actual information relevant to the alert.
The date and source IP variables seem to work fine but if/when I try to find/replace the TMPHEADERS, it causes strange symptoms including the entire output to be blank. I'm reasonably certain that it has to do with the headers containing lots of special characters (@ % & etc).
Can someone please advise on how best to accomplish this via bash?
My current code looks like this:
cat /test/emailtemplate | sed s/TMPHEADERS/"$HEADERS"/ > /test/output
UPDATE
As per request, here's an example set of headers I'm trying to insert into the template file (IP addresses and email address have been changed to protect the innocent :-) ):
From [email protected] Thu Apr 25 20:18:19 2013 Return-Path: <[email protected]> Received: from nm30-vm0.bullet.mail.ne1.yahoo.com (nm30-vm0.bullet.mail.ne1.yahoo.com [98.138.11.36]) by serv.example.com (8.14.4/8.14.4) with ESMTP id r3Q3IJVV009411 for <[email protected]>; Thu, 25 Apr 2013 20:18:19 -0700 Received: from [108.108.108.108] by nm30.bullet.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:19 -0000 Received: from [98.138.87.11] by tm15.bullet.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:17 -0000 Received: from [127.0.0.1] by omp1001.mail.ne1.yahoo.com with NNFMP; 26 Apr 2013 03:18:17 -0000 X-Yahoo-Newman-Property: ymail-3 X-Yahoo-Newman-Id: [email protected] Received: (qmail 29701 invoked by uid 65501); 26 Apr 2013 03:18:17 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s1024; t=1366946297; bh=yjMzVONHAyJxQob7tLNdIN2RpfGHWVw1Kb5Qr+enYF8=; h=X-YMail-OSG:Received:X-Rocket-MIMEInfo:X-Mailer:Message-ID:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=CQGilBx8NertE4j75dsfsdfs+IKRzIx5vlH5YdzqFLd4ThfEyMs11sdfsdfsdXsAH1yteACnwSER+QXJQ80BfLGbJnIWm+29I8A4geOPIHGKoOUCnPaD+/0bHfAps0JIcwEju8Tcvg4VDVWw= DomainKey-Signature:a=rsa-sha1; q=dns; c=nofws; s=s1024; d=yahoo.com; h=X-YMail-OSG:Received:X-Rocket-MIMEInfo:X-Mailer:Message-ID:Date:From:Reply-To:Subject:To:MIME-Version:Content-Type; b=5TIRL55VM2J2lPLsX9iCE4sdlkfjlEM2245M6qzg1oGrnZd61ykL4xQSsc3cYNz95fwNy67aRRC89n6xcti28ee5rjmlK0MDIskSB5sKlv165mNjmzF1LNx6uFXalI8QGSwiQt2uWLYvI7RrTVeZFELDfFVZyqygEl5k=; X-YMail-OSG: EDT4ym4VM1lVQMdtAQ5zqfE59jR1Mtip4vVL1fBzNxFdGvA YjAJ3MXC1EusloknrsPx3drxzR1b4PFErK.UhdgWePhK7TTCHhhju4XP4i7x 76WASceqp77T5itvZmilv5UuICJw3BCEd0fdADctfBYhLNwoALxjp6cnJMmE Z4dYVtlp5vUFqg1pHxqGOXqrtjeZffM4dMftnn.Q8LlVEkj3pZ6ZJV_kKFtj vGEGS5PAW0tIHWPEqVERYzmDOfF5sVSQLayPi6EM_i1OE038434laijEWbH0 nZt1Vkg3syO0t1BaTLN4B1bXeS8cv3GlbLO4ot7zVwA3sH4UhsC5M6xiWNFU 3iroObJ5BObL99VO3ktvC4KzekAWJ_fE85TQJhQKj6Iolgb4xlWa2x414xuA awO4pJI9grDjycUcmhmKwLZEt_.0OBLfSi5MSviaiCNMuU5qIdHm7VCGdORP Mc68rDkpmJE9I9Z.QZfhH5cFxqqmpyIOMTs0iIBGYz5d9QHMWCuo- Received: from [102.102.102.102] by web12341105.mail.ne1.yahoo.com via HTTP; Thu, 25 Apr 2013 20:18:17 PDT X-Rocket-MIMEInfo: 002.001,VGVzdGluZyAxMjMgTGEgbGEgbGEBMAEBAQE- X-Mailer: YahooMailWebService/0.8.141.536 Message-ID: <[email protected]> Date: Thu, 25 Apr 2013 20:18:17 -0700 (PDT) From: Test Account <[email protected]> Reply-To: Test Account <[email protected]> Subject: Test To: "[email protected]" <[email protected]> MIME-Version: 1.0 Content-Type: multipart/alternative; boundary="102743210-1541163991-1366946297=:49149"
-
manatwork almost 11 yearsSimple text manipulation tools have limitations, they are suitable only for basic template handling. Better see Tool to create text files from a template. Has links to similar Stack Exchange and Server Fault questions, see those too.
-
terdon almost 11 yearsCould you give us some examples of the headers that fail?
-
Mike B almost 11 years@terdon Absolutely. I updated the question to include some example headers (with different ips and email addresses).
-
-
Hauke Laging almost 11 years@terdon Indeed, that was the wrong variable. sed does not expand anything (due to the escaping of every char in the variable). What do you mean? Have you tried this, doesn't it work?
-
terdon almost 11 yearsMy bad, I always quote my
sed
commands (I thought that was necessary) and bash variables are not expanded (I mean that 's/foo/$bar/' actually printed$bar
and not the variable's contents). Your command worked fine without the quotes (as you had posted it) it failed when I put it in single quotes. Sorry, force of habit, feell free to roll back my edit. -
Mike B almost 11 yearsThanks for the prompt help but I'm getting an error:
sed: -e expression #1, char 121: unterminated
s' command` I'm guessing I must have configured the command wrong:sed "s/TMPHEADERS/$HEADERS_ESCAPED/" /home/foo/scripts/fooalert/emailtemplate > /home/foo/scripts/fooalert/testing1234
I've confirmed that the headers are now all escaped properly. -
Mike B almost 11 yearsI respect this answer but unfortunately I don't know perl well enough to maintain it on an on-going basis. I realize that's not a good answer (or reason not to use more efficient code). Thanks.
-
Hauke Laging almost 11 years@MikeB Can you find out what char causes the problem? I am not sure whether it is possible to have a newline in the replacement text. Is it possible that $HEADERS_ESCAPED contains a newline?
-
dimo414 about 3 years+1 to this approach, configuring
awk
's environment is much less error-prone than trying to wrestle withsed
's syntax.