File handle Variable scope issue

Discussion in 'Perl Misc' started by Truthless, Dec 30, 2003.

  1. Truthless

    Truthless Guest

    Hello All,

    I am somewhat new to perl and I am having some difficulty with a cgi
    script that I am making. This script is supposed to read a html file and
    replace certain sections of it with its own variables.

    Code similar to this works great. as long as $html is in the actual script.

    $variables = "Hello World";
    $html = '<h1>'.$variables.'</h1>';

    sub print_html {
    print "Content-type:text/html\n\n";
    print <<End_of_Bottom;
    $html
    End_of_Bottom
    }

    This outputs <h1>Hello World</h1>.

    The issue I am having is getting the $variables to be parsed if the html
    is pulled from a file. As I am doing here...

    $confile = 'myfile.html'; #file with <h1>$variables</h1> in it

    sub openconf {
    open(content,"$confile") or dienice("Cant open $confile : $!");
    @ary = <content>;
    close(content);
    foreach $line (@ary) {
    chomp($line);
    print "$line\n";
    }
    }

    This will print <h1>$variables</h1>, rather than the desired <h1>Hello
    World</h1>.

    Could any of you please tell me what I can do to make the variables in
    the strings that come from the file handle actually evaluate? There must
    be something basic I am looking for.

    Thank you for any help.


    T.
     
    Truthless, Dec 30, 2003
    #1
    1. Advertising

  2. "Truthless" <> wrote in message
    news:sIoIb.189489$...

    [snipped why are not variables like here-documents]

    > Could any of you please tell me what I can do to make the variables in
    > the strings that come from the file handle actually evaluate? There must
    > be something basic I am looking for.


    yes to make the variables actually *evaluate*, you could use *eval*

    this is discussed in fact in the FAQ:
    perldoc -q "How can I expand variables in text strings"

    personally I prefer to use a hash:

    $subs=(a=>'b', foo=>'bar');
    $text='some text containing easily matched markers like %a% or %foo%';
    $text=~s/%(\w+)%/$subs{$1}/g;

    this way, $text can safely be read from a file that others can modify, even
    if i dont trust them
    not to put something nasty in it.

    gnari
     
    Ragnar Hafstað, Dec 31, 2003
    #2
    1. Advertising

  3. "Truthless" <> wrote in message
    news:sIoIb.189489$...

    [snipped variable expantion puzzle]

    wierd choice of Subject line, by the way.

    gnari
     
    Ragnar Hafstað, Dec 31, 2003
    #3
  4. Truthless <> wrote:

    > This script is supposed to read a html file and
    > replace certain sections of it with its own variables.



    There are plenty of already designed, implemented, tested and
    supported templating systems.

    I'd use one of those rather than invent yet another one...

    You don't need to do this. It has already been done (repeatedly).


    > The issue I am having is getting the $variables to be parsed if the html
    > is pulled from a file. As I am doing here...



    > open(content,"$confile") or dienice("Cant open $confile : $!");



    That will break when the Next Version of Perl introduces a
    new function named content().

    You should use UPPER CASE for filehandles.

    You also have a useless use of double quotes, see the Perl FAQ:

    What's wrong with always quoting "$vars"?


    open(CONTENT, $confile) or dienice("Cant open '$confile' : $!");


    > @ary = <content>;


    my $html = join '', <CONTENT>; # a slow and tedious way of slurping


    > There must
    > be something basic I am looking for.



    Lookup the $/ variable in perlvar.pod.

    Enable slurp mode.


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Dec 31, 2003
    #4
  5. In article <>,
    (Tad McClellan) wrote:

    > Truthless <> wrote:
    >
    > > @ary = <content>;

    >
    > my $html = join '', <CONTENT>; # a slow and tedious way of slurping


    <snip>
    >
    >
    > Lookup the $/ variable in perlvar.pod.
    >
    > Enable slurp mode.


    You might also want to read:

    http://www.perl.com/pub/a/2003/11/21/slurp.html

    "Perl Slurp-Eaze
    by Uri Guttman"


    cheers,

    big

    --
    'When I first met Katho, she had a meat cleaver in one hand and
    half a sheep in the other. "Come in", she says, "Hammo's not here.
    I hope you like meat.' Sharkey in aus.moto
     
    Iain Chalmers, Dec 31, 2003
    #5
  6. Truthless

    Truthless Guest

    Iain Chalmers wrote:
    > In article <>,
    > (Tad McClellan) wrote:
    > <snip>
    >>Lookup the $/ variable in perlvar.pod.
    >>
    >>Enable slurp mode.

    >
    > You might also want to read:
    >
    > http://www.perl.com/pub/a/2003/11/21/slurp.html
    > big
    >



    Thanks, but I still have questions.
    I read that link and what I could take from it I've tried to use.

    $var = "Hello World";
    sub openconf {
    local( $/, *CONF ) ;
    open(CONF,$confile) or dienice("Cant open $confile : $!");
    $text = <CONF>
    }
    print "$text";

    The trouble is that
    print "$text"; gives me the literal strings from the file and goes not
    expand the variables within. I still get <h1>$var</h1>. I am not certain
    what is needed to make it display <h1>Hello World</h1> The perldocs are
    very good but I think I need an example. I see a lot of the docs have
    regex or something like this $text =~ s/(\$\w+)/$1/eeg; I am not certain
    what direction I should be going here. If I plant $vars in any
    other type of string variable it works great.

    $var = "Hello World";
    $text = "This is a string of text $var";
    print "$text";


    The above outputs


    This is a string of text Hello World.

    Why is it that when the string of text comes from a file handle it does
    not expand? What can I do to make it expand properly?

    Thank you.
     
    Truthless, Dec 31, 2003
    #6
  7. Truthless

    Truthless Guest

    Tad McClellan wrote:
    > Truthless <> wrote:


    > There are plenty of already designed, implemented, tested and
    > supported templating systems.
    >
    > I'd use one of those rather than invent yet another one...
    >
    > You don't need to do this. It has already been done (repeatedly).


    That won't help me learn CGI :)

    > Lookup the $/ variable in perlvar.pod.
    >
    > Enable slurp mode.


    I think I have the slurp down but the variables do not expand.

    sub openconf {
    local( $/, *CONF ) ;
    open(CONF,$confile) or dienice("Cant open $confile : $!");
    $text = <CONF>
    }


    Any ideas. The perldocs are very complete but a little much I just need
    an example.

    Thanks in advance.

    T
     
    Truthless, Dec 31, 2003
    #7
  8. Truthless

    Truthless Guest

    Gunnar Hjalmarsson wrote:
    > Truthless wrote:
    >
    >> The trouble is that print "$text"; gives me the literal strings


    >> lot of the docs have regex or something like this
    >> $text =~ s/(\$\w+)/$1/eeg;


    > But that is an example! Why don't you try it in your code?


    > $text = 'This is a string of text $var';
    > ------------^-----------------------------^
    >
    > you notice a difference. You need to understand the difference between
    > a literal and an interpolated string, i.e. the difference between
    > using single-quotes and double-quotes when quoting a string.
    >
    >

    Hello,

    sub openconf {
    local( $/, *CONF ) ;
    open(CONF,$confile) or dienice("Cant open $confile : $!");
    $text = <CONF>;
    $text =~ s/(\$\w+)/$1/eeg;
    }


    The $text =~ s/(\$\w+)/$1/eeg; trick worked but I am not certain what it
    is doing exactly. Is it regex that simply looks for $anything ? I guess
    I need to learn more regex.
    Double quotes and single quotes as with many scripting languages are the
    same. Usually " means interpret and ' means literally. I had more than
    one response mention the quotes, I was not sure exactly what the quoting
    issue was since I WAS using " and I wanted variables expanded.

    Thanks for the sugestion,
    perhaps some one could parphrase the
    $text =~ s/(\$\w+)/$1/eeg; assignment for me.

    TIA,
     
    Truthless, Dec 31, 2003
    #8
  9. Truthless wrote:
    > The trouble is that print "$text"; gives me the literal strings
    > from the file and goes not expand the variables within. I still get
    > <h1>$var</h1>.


    <snip>

    > The perldocs are very good but I think I need an example. I see a
    > lot of the docs have regex or something like this
    > $text =~ s/(\$\w+)/$1/eeg;


    But that is an example! Why don't you try it in your code?

    > If I plant $vars in any other type of string variable it works
    > great.
    >
    > $var = "Hello World";
    > $text = "This is a string of text $var";
    > print "$text";


    But if you do:

    $text = 'This is a string of text $var';
    ------------^-----------------------------^

    you notice a difference. You need to understand the difference between
    a literal and an interpolated string, i.e. the difference between
    using single-quotes and double-quotes when quoting a string.

    http://www.perldoc.com/perl5.8.0/pod/perlintro.html#Basic-syntax-overview

    When you read data from a file, nothing gets interpolated, so it is
    similar to using single-quotes, so to say.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Dec 31, 2003
    #9
  10. It was a dark and stormy night, and Truthless managed to scribble:

    > Hello All,
    >
    > I am somewhat new to perl and I am having some difficulty with a cgi
    > script that I am making. This script is supposed to read a html file and
    > replace certain sections of it with its own variables.
    >
    > Code similar to this works great. as long as $html is in the actual
    > script.
    >
    > $variables = "Hello World";
    > $html = '<h1>'.$variables.'</h1>';
    >
    > sub print_html {
    > print "Content-type:text/html\n\n";
    > print <<End_of_Bottom;
    > $html
    > End_of_Bottom
    > }
    >
    > This outputs <h1>Hello World</h1>.
    >
    > The issue I am having is getting the $variables to be parsed if the html
    > is pulled from a file. As I am doing here...
    >
    > $confile = 'myfile.html'; #file with <h1>$variables</h1> in it
    >
    > sub openconf {
    > open(content,"$confile") or dienice("Cant open $confile : $!");
    > @ary = <content>;
    > close(content);
    > foreach $line (@ary) {
    > chomp($line);
    > print "$line\n";
    > }
    > }
    >
    > This will print <h1>$variables</h1>, rather than the desired <h1>Hello
    > World</h1>.
    >
    > Could any of you please tell me what I can do to make the variables in
    > the strings that come from the file handle actually evaluate? There must
    > be something basic I am looking for.
    >
    > Thank you for any help.
    >


    Err, yes. Your brain was at there I was at about 3 years ago. You can use Perl templates but there's nothing like getting your hands dirty!

    Here's the Rolls Royce version of what you want:



    open(INFILE, 'myfile.htm');
    foreach (<INFILE>) {
    s/(\$\w+:):\w+)?)/$1/eeg;
    print;
    }

    WARNING: because this does command substitution and evaluation, it can there are security issues and is dangerous in the wrong hands.

    This works with lexical variables like $var. It also works with package variables like $var1::var2.


    Another question you will soon ask youself is "well if I can evaluate a variable, can I evaluate a function/subroutine." The answer is yes, providing you provide a return value & use the weird Perl syntax @{[subroutine_name()]}

    EXAMPLE: define a subroutine testsub in your main program

    sub testsub {return "This could be anything" }

    Then myfile.html could contain the following 3 lines:
    Hello World
    @{[testsub()]}
    Line 3


    gtoomey


    gtoomey
     
    Gregory Toomey, Dec 31, 2003
    #10
  11. Truthless wrote:
    > Gunnar Hjalmarsson wrote:
    >> Truthless wrote:
    >>> lot of the docs have regex or something like this
    >>> $text =~ s/(\$\w+)/$1/eeg;

    >>
    >> But that is an example! Why don't you try it in your code?

    >
    > sub openconf {
    > local( $/, *CONF ) ;
    > open(CONF,$confile) or dienice("Cant open $confile : $!");
    > $text = <CONF>;
    > $text =~ s/(\$\w+)/$1/eeg;
    > }
    >
    > The $text =~ s/(\$\w+)/$1/eeg; trick worked but I am not certain
    > what it is doing exactly. Is it regex that simply looks for
    > $anything ?


    It's more than a regex.

    http://www.perldoc.com/perl5.8.0/pod/perlop.html#s-PATTERN-REPLACEMENT-egimosx

    Most is explained there, except for the actual regex part of it.

    The PATTERN, i.e. /(\$\w+)/, consists of a regex that matches a '$'
    character followed by one or more word characters. The parentheses
    capture the matched substring into a capture buffer, which is referred
    to in REPLACEMENT through the special $1 variable.

    > I guess I need to learn more regex.


    Don't we all. ;-)

    http://www.perldoc.com/perl5.8.0/pod/perlre.html

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
     
    Gunnar Hjalmarsson, Dec 31, 2003
    #11
  12. Truthless

    Tore Aursand Guest

    On Wed, 31 Dec 2003 03:00:35 +0000, Truthless wrote:
    >> You don't need to do this. It has already been done (repeatedly).


    > That won't help me learn CGI :)


    Yes, it does; You - as a programmer - can focus on the functionality of
    your scripts/applications, rather then being hung up in details about
    separating code from design (which I think this is all about).

    Take a look at HTML::Template [1]. I think it does excactly what you
    need, and it doesn't let you "forget about" learning CGI programming, as
    separating code from design has nothing to do with CGI.

    [1] Just an example; There are many other templating modules out there,
    and a search for 'template' on <http://www.cpan.org/> will help you out
    choosing the right one.


    --
    Tore Aursand <>
    "Out of missiles. Out of bullets. Down to harsh language." -- Unknown
     
    Tore Aursand, Dec 31, 2003
    #12
  13. Truthless <> wrote:
    > Tad McClellan wrote:
    >> Truthless <> wrote:



    > That won't help me learn CGI :)



    We usually assume that questions asked here are for Real Programs.

    If you are doing it for a learning exercise, then you should say so,
    else we are likely to apply Software Engineering to your problem.


    > I have the slurp down but the variables do not expand.

    ^^^^^^
    ^^^^^^
    > Any ideas.



    perldoc -q expand

    How can I expand variables in text strings?


    > The perldocs are very complete but a little much



    We could help you understand them if you told us what part(s) it
    is that you are having trouble with...


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, Dec 31, 2003
    #13
  14. (Tad McClellan) writes:

    > Truthless <> wrote:
    > > Tad McClellan wrote:
    > >> Truthless <> wrote:

    >
    >
    > > That won't help me learn CGI :)

    >
    >
    > We usually assume that questions asked here are for Real Programs.
    >
    > If you are doing it for a learning exercise, then you should say so,
    > else we are likely to apply Software Engineering to your problem.
    >
    >
    > > I have the slurp down but the variables do not expand.

    > ^^^^^^
    > ^^^^^^
    > > Any ideas.

    >
    >
    > perldoc -q expand
    >
    > How can I expand variables in text strings?


    Take note, the FAQ doesn't tell you the simple answer because the FAQ
    maintainers assume people are too dumb to know when it is safe to apply
    the simple answer.

    The FAQ, in effect, tells you to roll your own simple templating
    system.

    You can, however use one of Perl's built-in templating systems (string
    interpolation).

    chop ( my $expanded = eval "<<__EOL__\n$string\n__EOL__" );
    die $@ if $@;

    This, of course, gives the author of the data in $string the ability
    to execute arbitrary code. Often this is a very bad thing (when they
    are not trusted). On the other hand often it is a very good thing
    (when you want a full-featured templating system).

    It is true that some people are dumb enough to use this even when it
    is a bad thing. However, refusing to put the eval solution in the FAQ
    (with suitable warnings) won't protect them. Refusing to put the
    simple answer in the FAQ means that:

    People will use the clumsy (roll-your-own templating system)
    solution even when the simple (eval) one is applicable.

    As people need more fancy templating features their hand-rolled
    templating systems will grow.

    When people discover the simple solution (for themselves or from
    other sources) they may not be warned of the dangers.

    When people discover the simple solution they will loose faith in
    the FAQ.

    --
    \\ ( )
    . _\\__[oo
    .__/ \\ /\@
    . l___\\
    # ll l\\
    ###LL LL\\
     
    Brian McCauley, Jan 2, 2004
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Dietrich
    Replies:
    1
    Views:
    656
    Joe Smith
    Jul 22, 2004
  2. Paul Opal
    Replies:
    12
    Views:
    973
    Paul Opal
    Oct 11, 2004
  3. David Filmer
    Replies:
    19
    Views:
    256
    Kevin Collins
    May 21, 2004
  4. Replies:
    0
    Views:
    171
  5. Andrew Falanga
    Replies:
    2
    Views:
    205
    Andrew Falanga
    Nov 22, 2008
Loading...

Share This Page