Comment puis-je utiliser SED ou AWK pour remplacer les espaces réservés dans un fichier modèle avec un contenu variable qui contient des caractères spéciaux?

8

CentOS 6.3

J'essaie d'obtenir un petit script pour envoyer un e-mail contenant une copie des en-têtes d'e-mail dans le corps (à des fins de reporting interne).

Le fichier modèle contient les éléments suivants:

Alert Report

Alert has triggered at TMPDATE

HEADERS
-------
TMPHEADERS

SOURCE IP
---------
TMPSOURCEIP

Je souhaite que mon script trouve et remplace les espaces réservés "TMP" par des informations réelles pertinentes à l'alerte.

La date et les variables IP source semblent bien fonctionner mais si / quand j'essaie de trouver / remplacer les TMPHEADERS, cela provoque des symptômes étranges, y compris la sortie entière à être vide. Je suis raisonnablement certain que cela a à voir avec les en-têtes contenant beaucoup de caractères spéciaux (@% & etc).

Quelqu'un peut-il vous conseiller sur la meilleure façon d'accomplir cela via bash?

Mon code actuel ressemble à ceci:

cat /test/emailtemplate | sed s/TMPHEADERS/"$HEADERS"/ > /test/output

MISE À JOUR

Conformément à la demande, voici un exemple d'ensemble d'en-têtes que j'essaie d'insérer dans le fichier de modèle (les adresses IP et l'adresse e-mail ont été modifiées pour protéger les innocents :-)):

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"
Mike B
la source
2
Les outils de manipulation de texte simples ont des limites, ils ne conviennent qu'à la gestion de base des modèles. Mieux voir l' outil pour créer des fichiers texte à partir d'un modèle . A des liens vers des questions similaires sur Stack Exchange et sur les pannes de serveur , consultez-les également.
manatwork
Pourriez-vous nous donner quelques exemples des en-têtes qui échouent?
terdon
@terdon Absolument. J'ai mis à jour la question pour inclure des exemples d'en-têtes (avec différentes adresses IP et e-mail).
Mike B

Réponses:

7

C'est difficile dans sed car dans sed s/TMPHEADERS/"$HEADERS"/, la valeur de la variable est remplacée par le shell avant que la commande n'atteigne sed, donc des caractères comme &\/celui-ci apparaissent dans $HEADERSont une signification spéciale dans le texte de remplacement. Sed n'a pas de fonction de recherche variable.

Cette tâche est assez facile avec awk. Passez la HEADERSvariable dans l'environnement:

export HEADERS
</test/emailtemplate awk '
    {gsub(/^TMPHEADERS$/, environ["HEADERS"]); print}
' > /test/output

ou en tant que variable awk:

</test/emailtemplate awk -v HEADERS="$HEADERS" '
    {gsub(/^TMPHEADERS$/, HEADERS); print}
' > /test/output
Gilles 'SO- arrête d'être méchant'
la source
3

Il existe plusieurs possibilités:

sed Vous devez échapper à chaque caractère dans "$ HEADERS" pour sécuriser l'appel sed.

HEADERS_ESCAPED="$(echo "$HEADERS" | sed -n 's/./\\&/gp')"
# double-useless use of cat BTW
sed "s/TMPHEADERS/$HEADERS_ESCAPED/" /test/emailtemplate > /test/output

BTW: Il n'y a absolument aucune raison d'appeler sed une fois pour chaque changement:

sed -n -e s/X/"$X"/ -e s/Y/"$Y" -e s/Z/"$Z"/ -e p inputfile > outputfile

se frapper

while IFS= read -r line; do
  line="${line/TMPDATE/"$TMPDATE"}"
  # ...
  line="${line/TMPHEADERS/"$HEADERS"}"
  printf '%s\n' "$line"
done <inputfile >outputfile
Hauke ​​Laging
la source
@terdon En effet, ce n'était pas la bonne variable. sed ne développe rien (en raison de l'échappement de chaque caractère dans la variable). Que voulez-vous dire? Avez-vous essayé cela, ça ne marche pas?
Hauke ​​Laging du
Mon mauvais, je cite toujours mes sedcommandes (je pensais que c'était nécessaire) et les variables bash ne sont pas développées (je veux dire que 's / foo / $ bar /' est réellement imprimé $baret non le contenu de la variable). Votre commande a bien fonctionné sans les guillemets (comme vous l'aviez posté), elle a échoué lorsque je l'ai mise entre guillemets simples. Désolé, force d'habitude, n'hésitez pas à annuler ma modification.
terdon
Merci pour l'aide rapide mais sed: -e expression #1, char 121: unterminated j'obtiens une erreur: s 'commande` Je suppose que je dois avoir mal configuré la commande: sed "s/TMPHEADERS/$HEADERS_ESCAPED/" /home/foo/scripts/fooalert/emailtemplate > /home/foo/scripts/fooalert/testing1234 j'ai confirmé que les en-têtes sont maintenant tous correctement échappés.
Mike B
@MikeB Pouvez-vous découvrir quel caractère cause le problème? Je ne sais pas s'il est possible d'avoir une nouvelle ligne dans le texte de remplacement. Est-il possible que $ HEADERS_ESCAPED contienne une nouvelle ligne?
Hauke ​​Laging du
1

Je ne suis pas sûr de comprendre ce que vous voulez faire. Si vous souhaitez, par exemple, remplacer la chaîne TMPHEADERSpar la longue liste d'informations d'en-tête que vous avez publiées, cette solution Perl peut le faire:

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 

Le fichier templateest le modèle de votre question et le fichier headercontient les lignes d'en-tête que vous avez publiées. Le résultat est

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

Vous pouvez l'étendre pour deux ensembles d'en-têtes comme suit:

perl -e 'open(A,"header1");
         $h1=join("",<A>);
         open(B,"header2");
         $h2=join("",<B>);
         while(<>){
            s/TMPHEADERS/$h1/;
            s/TMPSOURCEIP/$h2/;
            print        
         }' template 
terdon
la source
Je respecte cette réponse mais malheureusement je ne connais pas assez bien perl pour la maintenir en permanence. Je me rends compte que ce n'est pas une bonne réponse (ou raison de ne pas utiliser de code plus efficace). Merci.
Mike B
1

Utiliser le m4macro processeur pour remplacer TMPSOURCEIPet TMPDATEavec les choses définies sur la ligne de commande et TMPHEADERSavec tout ce qui est dans le fichier headers.txt. Le modèle est en 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 foo@yahoo.com Thu Apr 25 20:18:19 2013
Return-Path: <foo@yahoo.com>
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

Si vous avez déjà les en-têtes dans une variable, vous pouvez évidemment remplacer -DTMPHEADERS='include(headers.txt)'par -DTMPHEADERS="$headers".

Kusalananda
la source