Bagaimana saya bisa menggunakan SED atau AWK untuk menggantikan placeholder dalam file template dengan konten variabel yang berisi karakter khusus?

8

CentOS 6.3

Saya mencoba membuat skrip kecil untuk mengirim email yang berisi salinan tajuk email di badan (untuk tujuan pelaporan internal).

File template berisi yang berikut ini:

Alert Report

Alert has triggered at TMPDATE

HEADERS
-------
TMPHEADERS

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

Saya ingin skrip saya menemukan dan mengganti tempat tempat "TMP" dengan informasi aktual yang relevan dengan lansiran.

Variabel tanggal dan sumber IP tampaknya berfungsi dengan baik tetapi jika / ketika saya mencoba menemukan / mengganti TMPHEADERS, itu menyebabkan gejala aneh termasuk seluruh output menjadi kosong. Saya cukup yakin bahwa itu ada hubungannya dengan header yang berisi banyak karakter khusus (@% & dll).

Bisakah seseorang memberi saran tentang cara terbaik untuk melakukannya melalui bash?

Kode saya saat ini terlihat seperti ini:

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

MEMPERBARUI

Sesuai permintaan, inilah contoh kumpulan header yang saya coba masukkan ke file templat (alamat IP dan alamat email telah diubah untuk melindungi yang tidak bersalah :-)):

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
sumber
2
Alat manipulasi teks sederhana memiliki keterbatasan, mereka hanya cocok untuk penanganan template dasar. Lebih baik lihat Alat untuk membuat file teks dari templat . Memiliki tautan ke pertanyaan Stack Exchange dan Server Fault yang serupa , lihat juga.
manatwork
Bisakah Anda memberi kami beberapa contoh header yang gagal?
terdon
@terdon Tentu saja. Saya memperbarui pertanyaan untuk menyertakan beberapa contoh tajuk (dengan ips dan alamat email yang berbeda).
Mike B

Jawaban:

7

Ini sulit dalam sed karena dalam sed s/TMPHEADERS/"$HEADERS"/, nilai variabel diganti oleh shell sebelum perintah mencapai sed, sehingga karakter seperti &\/itu muncul $HEADERSmemiliki makna khusus dalam teks pengganti. Sed tidak memiliki fasilitas pencarian variabel.

Tugas ini cukup mudah dengan awk. Lulus HEADERSvariabel di lingkungan:

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

atau sebagai variabel awk:

</test/emailtemplate awk -v HEADERS="$HEADERS" '
    {gsub(/^TMPHEADERS$/, HEADERS); print}
' > /test/output
Gilles 'SANGAT berhenti menjadi jahat'
sumber
3

Ada beberapa kemungkinan:

sed Anda harus melarikan diri setiap char di "$ HEADERS" untuk membuat panggilan sed aman.

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

BTW: Sama sekali tidak ada alasan untuk memanggil sed sekali untuk setiap perubahan:

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

pesta itu sendiri

while IFS= read -r line; do
  line="${line/TMPDATE/"$TMPDATE"}"
  # ...
  line="${line/TMPHEADERS/"$HEADERS"}"
  printf '%s\n' "$line"
done <inputfile >outputfile
Hauke ​​Laging
sumber
@terdon Memang, itu adalah variabel yang salah. sed tidak memperluas apa pun (karena pelarian setiap karakter dalam variabel). Apa maksudmu? Sudahkah Anda mencoba ini, tidakkah berhasil?
Hauke ​​Laging
Buruk saya, saya selalu mengutip sedperintah saya (saya pikir itu perlu) dan variabel bash tidak diperluas (maksud saya 's / foo / $ bar /' sebenarnya dicetak $bardan bukan isi variabel). Perintah Anda berfungsi dengan baik tanpa tanda kutip (seperti yang telah Anda posting) gagal ketika saya memasukkannya dalam tanda kutip tunggal. Maaf, paksaan karena kebiasaan, bebas untuk memutar kembali edit saya.
terdon
Terima kasih atas bantuan yang cepat tetapi saya mendapatkan kesalahan: sed: -e expression #1, char 121: unterminated s 'command` Saya kira saya pasti telah mengkonfigurasi perintah yang salah: sed "s/TMPHEADERS/$HEADERS_ESCAPED/" /home/foo/scripts/fooalert/emailtemplate > /home/foo/scripts/fooalert/testing1234 Saya telah mengkonfirmasi bahwa header sekarang semua lolos dengan benar.
Mike B
@MikeB Bisakah Anda mengetahui apa yang menyebabkan masalah? Saya tidak yakin apakah mungkin untuk memiliki baris baru dalam teks pengganti. Apakah mungkin $ HEADERS_ESCAPED berisi baris baru?
Hauke ​​Laging
1

Saya tidak yakin saya mengerti apa yang ingin Anda lakukan. Jika Anda ingin, misalnya, mengganti string TMPHEADERSdengan daftar panjang informasi header yang Anda posting, solusi Perl ini dapat melakukannya:

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 

File templateadalah templat dari pertanyaan Anda dan file tersebut headermemiliki garis tajuk yang Anda poskan. Hasilnya adalah

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

Anda dapat memperluas ini untuk dua set tajuk sebagai berikut:

perl -e 'open(A,"header1");
         $h1=join("",<A>);
         open(B,"header2");
         $h2=join("",<B>);
         while(<>){
            s/TMPHEADERS/$h1/;
            s/TMPSOURCEIP/$h2/;
            print        
         }' template 
terdon
sumber
Saya menghargai jawaban ini tetapi sayangnya saya tidak tahu perl cukup baik untuk mempertahankannya secara berkelanjutan. Saya menyadari bahwa itu bukan jawaban yang baik (atau alasan untuk tidak menggunakan kode yang lebih efisien). Terima kasih.
Mike B
1

Menggunakan m4prosesor makro untuk mengganti TMPSOURCEIPdan TMPDATEdengan hal-hal yang ditentukan pada baris perintah dan TMPHEADERSdengan apa pun yang ada di file headers.txt. Templat di 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

Jika Anda sudah memiliki header dalam variabel, Anda mungkin jelas mengganti -DTMPHEADERS='include(headers.txt)'dengan -DTMPHEADERS="$headers".

Kusalananda
sumber