in reply to hiccoughing here documents

I'm settling down to work through the suggestions so far, but I think I could usefully go into a bit more detail now that I've got a better idea of formatting etc. My apologies, I've been an occasional lurker for years but haven't barked before.

What I'm trying to do is take a pattern of some sort, and then to "hiccough" some (but not all) of the lines an indeterminate number of times. So on reflection- and my apologies for not being more explicit first time round- this might be a better example of the required output:

iptables -t nat -N outbound-DMZ iptables -t nat -A outbound-DMZ -o eth1.201 -j SNAT --to-source 90.145 +.84.155 iptables -t nat -A outbound-DMZ -o eth1.200 -j SNAT --to-source 90.145 +.84.155 iptables -t nat -A outbound-DMZ -j RETURN iptables -t nat -A POSTROUTING -j outbound-DMZ

where this shows that the repeated lines are typically in the middle of the block of text rather than at the beginning or end. One idea that occured to me was something like

$commands = &reinterpolate <<"EOF"; iptables -t nat -N outbound-DMZ foreach \$iface (keys \%ipAddress) { iptables -t nat -A outbound-DMZ -o \$iface -j SNAT --to-source \$ipA +ddress{\$iface} } iptables -t nat -A outbound-DMZ -j RETURN iptables -t nat -A POSTROUTING -j outbound-DMZ EOF

where &reinterpolate picks up the lines with and between braces and (eventually) applies eval(), but I can see that some of the suggestions are approaching that.

The system this would be running on is a minimal router, so if possible I'd like to avoid anything that isn't in a typical Linux distro.

MarkMLl

Replies are listed 'Best First'.
Re^2: hiccoughing here documents
by Anonymous Monk on Aug 12, 2017 at 15:55 UTC

    Something like this works:

    sub IFACE { my $pattern = shift @_; my $result; foreach $iface (@_) { $result .= (eval "\"$pattern\"") . "\n"; } chomp $result; return $result; } &utter( <<"EOF" ); iptables -t nat -N outbound-DMZ @{[ &IFACE( "iptables -t nat -A outbound-DMZ -s $lanCidr -o \$iface -j SNAT --to +-source $dmzIp", (keys %ipAddress)) ]} iptables -t nat -A outbound-DMZ -j RETURN EOF

    I know it's unconventional but I've capitalised the function name to emphasise its relationship to the name of the variable being interpolated, I felt that trying to pass that name as a parameter would be pushing my luck. It's (obviously) very sensitive to the double-quotes being correct, both in the function and in the heredoc itself. The one thing I wasn't able to get working was ~ to enable indents (5.20.2 on Debian Jessie armhf), but that's a fairly detail since the nearer the heredoc is to the actual stuff going into the tables the better.

    Many thanks to everybody, especially NetWallah.

    Pax vobiscum, MarkMLl

      Here's a version that's not quite so funky (but still kinda ugly). This is a situation in which a prototype is actually useful. If the  hiccup() function is defined in the source file in which it's used | invoked, either the full definition of the function or a prototype declaration must appear before first invocation of the function. If the function is moved to a module, a use statement must appear before first invocation.

      File hiccup_here_3.pl:

      use warnings; use strict; use Hic; # sub hiccup (&@); my $lanCidr = 'WHATEVER'; my $dmzIp = 'SOMEWHERE'; my %ipAddress = qw(HERE we_are THERE it_goes EVERYWHERE at_once); my @array = qw(WIBBLE BOFF); my $s = << "EOF"; iptables -t nat -N outbound-DMZ @{[ hiccup { "iptables -t nat -s $lanCidr -o $_ -j SNAT --to-source $dmzIp" } keys %ipAddress ]} whatever else here @{[ hiccup { "flocculate -f $_ -j SNAT --to-source $dmzIp" } @array ]} iptables -t nat -A outbound-DMZ -j RETURN EOF # sub hiccup (&@) { return join "\n", map $_[0]->(), @_[ 1 .. $#_ ]; } print "[[$s]]";

      Module Hic.pm:

      package Hic; use warnings; use strict; use parent 'Exporter'; our $VERSION = '0.1.0'; our @EXPORT = qw(hiccup); # default exported symbol(s) our @EXPORT_OK = qw(); # optional exported symbol(s) (none) sub hiccup (&@) { return join "\n", map $_[0]->(), @_[ 1 .. $#_ ]; } 1;

      However it's invoked, the function produces the following output:

      c:\@Work\Perl\monks\Anonymous Monk\1197277>perl hiccup_here_3.pl [[iptables -t nat -N outbound-DMZ iptables -t nat -s WHATEVER -o EVERYWHERE -j SNAT --to-source SOMEWHER +E iptables -t nat -s WHATEVER -o THERE -j SNAT --to-source SOMEWHERE iptables -t nat -s WHATEVER -o HERE -j SNAT --to-source SOMEWHERE whatever else here flocculate -f WIBBLE -j SNAT --to-source SOMEWHERE flocculate -f BOFF -j SNAT --to-source SOMEWHERE iptables -t nat -A outbound-DMZ -j RETURN ]]

      Update: Screwed up initial post of hiccup_here_3.pl file. Fixed.


      Give a man a fish:  <%-{-{-{-<