<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
		>
<channel>
	<title>Comments on: Generate Text From Templates, Scripts and CSV Data</title>
	<atom:link href="http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/feed/" rel="self" type="application/rss+xml" />
	<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/</link>
	<description>For savvy admins everywhere...</description>
	<lastBuildDate>Thu, 12 Aug 2010 19:36:06 -0700</lastBuildDate>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
	<item>
		<title>By: Marco</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-442</link>
		<dc:creator>Marco</dc:creator>
		<pubDate>Wed, 07 Oct 2009 15:57:26 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-442</guid>
		<description>Improved version. The original script breaks if there are white spaces in the fields. 

#!/bin/bash 
IMPORT=&quot;./data/import-data.txt&quot;
TEMPLATE=&quot;./data/import-template.txt&quot;

# for i in `cat ${IMPORT}`

cat $IMPORT &#124; \
while read i

do
# echo $i # debug

  VAR_HOSTNAME=`echo $i &#124; awk -F, &#039;{print $1}&#039;`
  VAR_IPADDR=`echo $i &#124; awk -F, &#039;{print $2}&#039;`
  VAR_NETMASK=`echo $i &#124; awk -F, &#039;{print $3}&#039;`
  VAR_OSPF_KEY=`echo $i &#124; awk -F, &#039;{print $4}&#039;`
  VAR_TACACS_KEY=`echo $i &#124; awk -F, &#039;{print $5}&#039;`
  cat $TEMPLATE &#124; sed -e &quot;s/VAR_HOSTNAME/$VAR_HOSTNAME/g&quot; \
                      -e &quot;s/VAR_IPADDR/$VAR_IPADDR/g&quot; \
                      -e &quot;s/VAR_NETMASK/$VAR_NETMASK/g&quot; \
                      -e &quot;s/VAR_OSPF_KEY/$VAR_OSPF_KEY/g&quot; \
                      -e &quot;s/VAR_TACACS_KEY/$VAR_TACACS_KEY/g&quot; \
                &#124; tee ./output/&quot;$VAR_HOSTNAME.txt&quot; 1&gt;/dev/null
done</description>
		<content:encoded><![CDATA[<p>Improved version. The original script breaks if there are white spaces in the fields. </p>
<p>#!/bin/bash<br />
IMPORT=&#8221;./data/import-data.txt&#8221;<br />
TEMPLATE=&#8221;./data/import-template.txt&#8221;</p>
<p># for i in `cat ${IMPORT}`</p>
<p>cat $IMPORT | \<br />
while read i</p>
<p>do<br />
# echo $i # debug</p>
<p>  VAR_HOSTNAME=`echo $i | awk -F, &#8216;{print $1}&#8217;`<br />
  VAR_IPADDR=`echo $i | awk -F, &#8216;{print $2}&#8217;`<br />
  VAR_NETMASK=`echo $i | awk -F, &#8216;{print $3}&#8217;`<br />
  VAR_OSPF_KEY=`echo $i | awk -F, &#8216;{print $4}&#8217;`<br />
  VAR_TACACS_KEY=`echo $i | awk -F, &#8216;{print $5}&#8217;`<br />
  cat $TEMPLATE | sed -e &#8220;s/VAR_HOSTNAME/$VAR_HOSTNAME/g&#8221; \<br />
                      -e &#8220;s/VAR_IPADDR/$VAR_IPADDR/g&#8221; \<br />
                      -e &#8220;s/VAR_NETMASK/$VAR_NETMASK/g&#8221; \<br />
                      -e &#8220;s/VAR_OSPF_KEY/$VAR_OSPF_KEY/g&#8221; \<br />
                      -e &#8220;s/VAR_TACACS_KEY/$VAR_TACACS_KEY/g&#8221; \<br />
                | tee ./output/&#8221;$VAR_HOSTNAME.txt&#8221; 1&gt;/dev/null<br />
done</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: gmendoza</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-415</link>
		<dc:creator>gmendoza</dc:creator>
		<pubDate>Mon, 24 Aug 2009 15:56:42 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-415</guid>
		<description>1&gt;file.txt sends output to a text file called &quot;file.txt&quot;.
1&gt;&gt;file.txt sends output to a text file called &quot;file.txt&quot;, but appends if it already exists.

2&gt;file.txt sends errors to a text file called &quot;file.txt&quot;.
2&gt;&gt;file.txt sends errors to a text file called &quot;file.txt&quot;, but appends if it already exists.

Here&#039;s a decent tutorial on the subject.
http://linux.about.com/library/bl/open/newbie/blnewbie3.4.7.htm

I&#039;m really glad this was able to help you.</description>
		<content:encoded><![CDATA[<p>1&gt;file.txt sends output to a text file called &#8220;file.txt&#8221;.<br />
1&gt;&gt;file.txt sends output to a text file called &#8220;file.txt&#8221;, but appends if it already exists.</p>
<p>2&gt;file.txt sends errors to a text file called &#8220;file.txt&#8221;.<br />
2&gt;&gt;file.txt sends errors to a text file called &#8220;file.txt&#8221;, but appends if it already exists.</p>
<p>Here&#8217;s a decent tutorial on the subject.<br />
<a href="http://linux.about.com/library/bl/open/newbie/blnewbie3.4.7.htm" rel="nofollow">http://linux.about.com/library/bl/open/newbie/blnewbie3.4.7.htm</a></p>
<p>I&#8217;m really glad this was able to help you.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Laz</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-414</link>
		<dc:creator>Laz</dc:creator>
		<pubDate>Mon, 24 Aug 2009 15:29:13 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-414</guid>
		<description>This has been extremely useful for both routers and switches. I had to configure about 45 devices, with this I was able to do it in about an hour after making the CSV file. I have one question though ( as I am a new to linux) what is &quot;1&gt;&gt;./output/$VAR_HOSTNAME.txt&quot; mean?

Thanks again!</description>
		<content:encoded><![CDATA[<p>This has been extremely useful for both routers and switches. I had to configure about 45 devices, with this I was able to do it in about an hour after making the CSV file. I have one question though ( as I am a new to linux) what is &#8220;1&gt;&gt;./output/$VAR_HOSTNAME.txt&#8221; mean?</p>
<p>Thanks again!</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: gmendoza</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-314</link>
		<dc:creator>gmendoza</dc:creator>
		<pubDate>Tue, 13 Jan 2009 05:31:16 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-314</guid>
		<description>@Herouth, Re: using tee...

Meh... that&#039;s actually kind of funny.  It was probably something left over from something else I was doing.  It could easily be replaced with:  1&gt;&gt;./output/$VAR_HOSTNAME.txt</description>
		<content:encoded><![CDATA[<p>@Herouth, Re: using tee&#8230;</p>
<p>Meh&#8230; that&#8217;s actually kind of funny.  It was probably something left over from something else I was doing.  It could easily be replaced with:  1>>./output/$VAR_HOSTNAME.txt</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Herouth</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-313</link>
		<dc:creator>Herouth</dc:creator>
		<pubDate>Mon, 12 Jan 2009 16:11:32 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-313</guid>
		<description>Oops, forgot the crucial part above: read -u 4</description>
		<content:encoded><![CDATA[<p>Oops, forgot the crucial part above: read -u 4</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Herouth</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-312</link>
		<dc:creator>Herouth</dc:creator>
		<pubDate>Mon, 12 Jan 2009 16:10:31 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-312</guid>
		<description>Here is how I would do the loop, which I think is more efficient (not invoking awk) - but requires that the import file does not have any empty fields:

exec 4&lt;&quot;$IMPORT&quot;

while IFS=&#039;,&#039; read VAR_HOSTNAME VAR_IPADDR VAR_NETMASK VAR_OSPF_KEY VAR_TACACS_KEY
do

# sed part remains unchanged

done

By the way, why are you using tee if you&#039;re not doing anything with standard output?</description>
		<content:encoded><![CDATA[<p>Here is how I would do the loop, which I think is more efficient (not invoking awk) &#8211; but requires that the import file does not have any empty fields:</p>
<p>exec 4&lt;&#8221;$IMPORT&#8221;</p>
<p>while IFS=&#8217;,&#8217; read VAR_HOSTNAME VAR_IPADDR VAR_NETMASK VAR_OSPF_KEY VAR_TACACS_KEY<br />
do</p>
<p># sed part remains unchanged</p>
<p>done</p>
<p>By the way, why are you using tee if you&#8217;re not doing anything with standard output?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Larry</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-87</link>
		<dc:creator>Larry</dc:creator>
		<pubDate>Mon, 10 Mar 2008 18:23:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-87</guid>
		<description>Sweet scripts, not that it&#039;s much use to me.</description>
		<content:encoded><![CDATA[<p>Sweet scripts, not that it&#8217;s much use to me.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: gmendoza</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-86</link>
		<dc:creator>gmendoza</dc:creator>
		<pubDate>Sun, 09 Mar 2008 16:46:58 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-86</guid>
		<description>Hey there, Blacky.  Thanks for contributing again.

The scenario I had in mind was purely for short-term time savings through bulk processing.  The whole point of using a CSV is that it&#039;s easy to import and parse thousands of records, as each iteration of the for-loop only has to process a single line to obtain the definitions separated by a delimiter.  For this type of task, creating a CSV is easier to generate than cpp precompiler directives for subsitution, because the latter as you pointed out requires not only multiple lines for the definitions, but multiple files to serve as the import data.  

However, what I really like about your suggestion is that if the intention is to maintain a version control system, individualizing the import data as a template of it&#039;s own would be quite beneficial!  Plus, you have the added benefit of simply being able to generate a single configuration from your cpp template, rather than having to create a new CSV for the job.

Now of course, I would still recommend using the method mentioned in the article to both generate and populate the cpp templates to get things started.  But for continual maintenance of such text, your suggestion is certainly one that readers should look into.

Thanks again.</description>
		<content:encoded><![CDATA[<p>Hey there, Blacky.  Thanks for contributing again.</p>
<p>The scenario I had in mind was purely for short-term time savings through bulk processing.  The whole point of using a CSV is that it&#8217;s easy to import and parse thousands of records, as each iteration of the for-loop only has to process a single line to obtain the definitions separated by a delimiter.  For this type of task, creating a CSV is easier to generate than cpp precompiler directives for subsitution, because the latter as you pointed out requires not only multiple lines for the definitions, but multiple files to serve as the import data.  </p>
<p>However, what I really like about your suggestion is that if the intention is to maintain a version control system, individualizing the import data as a template of it&#8217;s own would be quite beneficial!  Plus, you have the added benefit of simply being able to generate a single configuration from your cpp template, rather than having to create a new CSV for the job.</p>
<p>Now of course, I would still recommend using the method mentioned in the article to both generate and populate the cpp templates to get things started.  But for continual maintenance of such text, your suggestion is certainly one that readers should look into.</p>
<p>Thanks again.</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: blacky</title>
		<link>http://savvyadmin.com/generate-text-from-templates-scripts-and-csv-data/comment-page-1/#comment-85</link>
		<dc:creator>blacky</dc:creator>
		<pubDate>Sat, 08 Mar 2008 11:19:56 +0000</pubDate>
		<guid isPermaLink="false">http://www.savvyadmin.com/2008/03/06/generate-text-from-templates-scripts-and-csv-data/#comment-85</guid>
		<description>If the number of variables needed increases, the sed solution can
become quite unwieldy. Also, having different sets of defined
variables isn&#039;t quite as easy. Finally, if you have many switches
(and many admins), it may be easier to have one file per switch
to facilitate the use of a version control system. To this end,
using the C preprocessor (or a similar macro system) may be
useful. 

For example:

&lt;code&gt;
$ cat import-template.txt 
!
hostname HOSTNAME
!
interface Vlan100
 ip address IPADDR NETMASK
 ip ospf message-digest-key 1 md5 OSPF_KEY
!
tacacs-server host 1.1.1.1
tacacs-server key TACACS_KEY
!

$ cat switches/switch-01 
#define HOSTNAME switch-01
#define IPADDR 10.1.1.1
#define NETMASK 255.255.255.0
#define OSPF_KEY ospf-key-1
#define TACACS_KEY tacacs-key-1
$ cpp -P -include switches/switch-01 import-template.txt 


!
hostname switch-01
!
interface Vlan100
 ip address 10.1.1.1 255.255.255.0
 ip ospf message-digest-key 1 md5 ospf-key-1
!
tacacs-server host 1.1.1.1
tacacs-server key tacacs-key-1
!
&lt;/code&gt;</description>
		<content:encoded><![CDATA[<p>If the number of variables needed increases, the sed solution can<br />
become quite unwieldy. Also, having different sets of defined<br />
variables isn&#8217;t quite as easy. Finally, if you have many switches<br />
(and many admins), it may be easier to have one file per switch<br />
to facilitate the use of a version control system. To this end,<br />
using the C preprocessor (or a similar macro system) may be<br />
useful. </p>
<p>For example:</p>
<p><code><br />
$ cat import-template.txt<br />
!<br />
hostname HOSTNAME<br />
!<br />
interface Vlan100<br />
 ip address IPADDR NETMASK<br />
 ip ospf message-digest-key 1 md5 OSPF_KEY<br />
!<br />
tacacs-server host 1.1.1.1<br />
tacacs-server key TACACS_KEY<br />
!</p>
<p>$ cat switches/switch-01<br />
#define HOSTNAME switch-01<br />
#define IPADDR 10.1.1.1<br />
#define NETMASK 255.255.255.0<br />
#define OSPF_KEY ospf-key-1<br />
#define TACACS_KEY tacacs-key-1<br />
$ cpp -P -include switches/switch-01 import-template.txt </p>
<p>!<br />
hostname switch-01<br />
!<br />
interface Vlan100<br />
 ip address 10.1.1.1 255.255.255.0<br />
 ip ospf message-digest-key 1 md5 ospf-key-1<br />
!<br />
tacacs-server host 1.1.1.1<br />
tacacs-server key tacacs-key-1<br />
!<br />
</code></p>
]]></content:encoded>
	</item>
</channel>
</rss>
