Force interpolation of single quoted character

Discussion in 'Perl Misc' started by Scott Bass, May 27, 2005.

  1. Scott Bass

    Scott Bass Guest

    Hi,

    use Getopt::Long;
    GetOptions (
    "sep:s" => \$sep
    );
    $sep = "$sep"; # doesn't work
    print "line1",$sep,"line2";

    If I invoke this as --sep \n or --sep \t, how can I force the interpolation
    of the escapse sequence?

    Thanks,
    Scott
     
    Scott Bass, May 27, 2005
    #1
    1. Advertising

  2. Scott Bass

    Shawn Corey Guest

    Scott Bass wrote:
    > Hi,
    >
    > use Getopt::Long;
    > GetOptions (
    > "sep:s" => \$sep
    > );
    > $sep = "$sep"; # doesn't work
    > print "line1",$sep,"line2";
    >
    > If I invoke this as --sep \n or --sep \t, how can I force the interpolation
    > of the escapse sequence?
    >
    > Thanks,
    > Scott
    >
    >


    eval '$sep = "$sep";';

    --- Shawn
     
    Shawn Corey, May 27, 2005
    #2
    1. Advertising

  3. Scott Bass

    Scott Bass Guest

    "Shawn Corey" <> wrote in message
    news:CSDle.23740$...
    > Scott Bass wrote:
    >> Hi,
    >>
    >> use Getopt::Long;
    >> GetOptions (
    >> "sep:s" => \$sep
    >> );
    >> $sep = "$sep"; # doesn't work
    >> print "line1",$sep,"line2";
    >>
    >> If I invoke this as --sep \n or --sep \t, how can I force the
    >> interpolation of the escapse sequence?
    >>
    >> Thanks,
    >> Scott

    >
    > eval '$sep = "$sep";';
    >
    > --- Shawn


    test1.pl:

    use Getopt::Long;
    GetOptions (
    "sep:s" => \$sep
    );
    eval '$sep = "$sep";';
    print "line1",$sep,"line2";

    C:\> test.pl -sep "\n"

    gives me

    line1\nline2

    BTW, ActiveState Perl on Windows - wouldn't think that matters though.
     
    Scott Bass, May 27, 2005
    #3
  4. Shawn Corey wrote:
    > Scott Bass wrote:
    >
    >> Hi,
    >>
    >> use Getopt::Long;
    >> GetOptions (
    >> "sep:s" => \$sep
    >> );
    >> $sep = "$sep"; # doesn't work
    >> print "line1",$sep,"line2";
    >>
    >> If I invoke this as --sep \n or --sep \t, how can I force the
    >> interpolation of the escapse sequence?


    This is of course one FAQ.

    And very similar to another one.

    And as regular readers will know I find the fact that the answers given
    in the FAQ pretends the simple/obvious/direct answer does not exist a
    constant source of annoyance.

    I even gave a lightning talk at YAPC::Europe::2004 about it.

    This is because it means that people get shown (or figure out for
    themselves) the broken form of the obvious answer...

    > eval '$sep = "$sep";';


    .... yes, that's the one. That breaks if $sep contains double quote
    characters.

    The better version of that is...

    chop( $sep = eval "<<__EOD__\n$sep\n__EOD__");
    do_something if $@;

    That only breaks if $sep contains the sequence "\n__EOD__\n" which is
    much less likely to occur in the normal course of events.


    And also by excuding this "dangerous knowledge" from the FAQ the real
    effect is that people are simply are not warned of the security dangers
    of using eval(STING) on data that could come from someone who doesn't
    have a ligitmate way of getting full shell access (under the current
    effective UID).

    Note: for expanding escapes rather than interpolating variables the
    solution in the FAQ is probably better anyhow.
     
    Brian McCauley, May 27, 2005
    #4
  5. Brian McCauley wrote:

    > the broken form of the obvious answer...
    >
    >> eval '$sep = "$sep";';

    >
    > ... yes, that's the one.


    Oops, no it's not even that.

    The 'correct' broken form is...

    eval qq'$sep = "$sep";';

    But it's still better to use the less broken form, or better still the
    FAQ solution.
     
    Brian McCauley, May 27, 2005
    #5
  6. Scott Bass <> wrote:
    > Hi,
    >
    > use Getopt::Long;
    > GetOptions (
    > "sep:s" => \$sep
    > );
    > $sep = "$sep"; # doesn't work
    > print "line1",$sep,"line2";
    >
    > If I invoke this as --sep \n or --sep \t,



    Then you would have $sep eq 'n' or $sep eq 't', so I'll assume that
    you meant

    --sep '\n'

    instead.


    > how can I force the interpolation
    > of the escapse sequence?



    I would solve the problem without the need for forcing interpolation.

    ------------------------------
    #!/usr/bin/perl
    use warnings;
    use strict;
    use Getopt::Long;

    our $sep;
    GetOptions (
    "sep:s" => \$sep
    );

    my %separators = (
    '\n' => "\n",
    '\t' => "\t"
    );
    die "'$sep' is not a valid separator\n" unless $sep =~ /^(\\[tn])$/;

    $sep = $separators{$sep};
    print "line1",$sep,"line2";
    print "\n";
    ------------------------------


    --
    Tad McClellan SGML consulting
    Perl programming
    Fort Worth, Texas
     
    Tad McClellan, May 27, 2005
    #6
  7. Scott Bass

    Scott Bass Guest

    "Tad McClellan" <> wrote in message
    news:...
    > Scott Bass <> wrote:
    >> Hi,
    >>
    >> use Getopt::Long;
    >> GetOptions (
    >> "sep:s" => \$sep
    >> );
    >> $sep = "$sep"; # doesn't work
    >> print "line1",$sep,"line2";
    >>
    >> If I invoke this as --sep \n or --sep \t,

    >
    >
    > Then you would have $sep eq 'n' or $sep eq 't', so I'll assume that
    > you meant
    >
    > --sep '\n'
    >
    > instead.


    Yes, command line options of -sep \n, -sep \t, etc. However, -sep \n, -sep
    "\n", or -sep '\n' all seem to give the same results after processing by
    GetOptions.

    >> how can I force the interpolation
    >> of the escapse sequence?

    >
    >
    > I would solve the problem without the need for forcing interpolation.
    >
    > ------------------------------
    > #!/usr/bin/perl
    > use warnings;
    > use strict;
    > use Getopt::Long;
    >
    > our $sep;
    > GetOptions (
    > "sep:s" => \$sep
    > );
    >
    > my %separators = (
    > '\n' => "\n",
    > '\t' => "\t"
    > );
    > die "'$sep' is not a valid separator\n" unless $sep =~ /^(\\[tn])$/;
    >
    > $sep = $separators{$sep};
    > print "line1",$sep,"line2";
    > print "\n";


    Sorry I oversimplied my post for the purpose of brevity. I'd like the users
    of my script to be able to specify, for example:

    -sep \n=====\n
    -sep \n\n\n\
    -sep \t
    -sep #

    etc.

    Brian, based on your replies, I skimmed all the FAQ's, esp. perlfaq4. Can I
    have a hint as to which FAQ this is explained?

    > ------------------------------
    >
    >
    > --
    > Tad McClellan SGML consulting
    > Perl programming
    > Fort Worth, Texas
     
    Scott Bass, May 27, 2005
    #7
  8. Scott Bass wrote:

    > "Tad McClellan" <> wrote in message
    > news:...


    [snip Tad ]

    > Brian,


    It would keep the thread cleaner if you were to post the follow-up to me
    as a follow-up to me.

    > based on your replies, I skimmed all the FAQ's, esp. perlfaq4. Can I
    > have a hint as to which FAQ this is explained?


    The question you are asking _is_ frequently asked, but I think I'd
    confused myself and then in turn you too.

    The FAQ "How do I unescape a string?" does _not_ answer your question.
    Nor does the FAQ "How can I expand variables in text strings?".

    Both of these _should_ IMNSHO mention the chop-eval-heredoc solution if
    only so that they can explain when it is unsafe to use. I have in the
    past battled with FAQ maintainers on this issue but never got very far.

    I have to confess that I mis-remebered the FAQ "How do I unescape a
    string?" as giving Tad's solution. May I be placed in virtual stocks
    and pelted with virtual rotten fruit for not checking my facts before I
    posted.
     
    Brian McCauley, May 27, 2005
    #8
  9. Brian McCauley wrote:

    > Both of these _should_ IMNSHO mention the chop-eval-heredoc solution if
    > only so that they can explain when it is unsafe to use.


    BTW: here's a slightly safer eval based solution

    s/(\\[^"\$\@]+)/qq("$1")/eeg;

    Note that's not 100% infalible but AFAIK it's not a security problem and
    copes with all reasonable strings. It does have the interesting side
    effect of stripping \$ \" and \@ - but those have no buisness being in
    the strings you are talking about.
     
    Brian McCauley, May 27, 2005
    #9
  10. Scott Bass

    Scott Bass Guest

    "Brian McCauley" <> wrote in message
    news:d77pkf$473$...
    > Scott Bass wrote:
    >
    >> "Tad McClellan" <> wrote in message
    >> news:...

    >
    > [snip Tad ]
    >
    > [snip Brian]
    >
    > The question you are asking _is_ frequently asked, but I think I'd
    > confused myself and then in turn you too.
    >
    > The FAQ "How do I unescape a string?" does _not_ answer your question. Nor
    > does the FAQ "How can I expand variables in text strings?".
    >
    > Both of these _should_ IMNSHO mention the chop-eval-heredoc solution if
    > only so that they can explain when it is unsafe to use. I have in the
    > past battled with FAQ maintainers on this issue but never got very far.
    >
    > I have to confess that I mis-remebered the FAQ "How do I unescape a
    > string?" as giving Tad's solution. May I be placed in virtual stocks and
    > pelted with virtual rotten fruit for not checking my facts before I
    > posted.


    Hey, happens to the best of us ;-) I've even been known to do it on rare
    occasions.

    Summary of Brian's previous posts:

    > The better version of that is...
    >
    > chop( $sep = eval "<<__EOD__\n$sep\n__EOD__");
    > do_something if $@;
    >
    > That only breaks if $sep contains the sequence "\n__EOD__\n" which is much
    > less likely to occur in the normal course of events.


    and

    > BTW: here's a slightly safer eval based solution


    I assume that should be "non eval based solution"?

    >
    > s/(\\[^"\$\@]+)/qq("$1")/eeg;
    >
    > Note that's not 100% infalible but AFAIK it's not a security problem and
    > copes with all reasonable strings. It does have the interesting side
    > effect of stripping \$ \" and \@ - but those have no buisness being in the
    > strings you are talking about.


    Thanks for the help Brian. In my final test program:

    use Getopt::Long;
    GetOptions (
    "sep:s" => \$sep
    );
    #chop($sep = eval "<<__$$__\n$sep\n__$$__");
    $sep =~ s/(\\[^"\$\@]+)/qq("$1")/eeg;
    print join $sep, ("line1","line2");

    both solutions work a treat. I'll go with the here doc solution; it's an
    internal, departmental script, and the end user's won't be putting cruft in
    the command line option.

    Regards,
    Scott
     
    Scott Bass, May 29, 2005
    #10
  11. Scott Bass

    Scott Bass Guest

    "Scott Bass" <usenet739_yahoo_com_au> wrote in message
    news:42991803$0$24303$...

    [snip]

    > Thanks for the help Brian. In my final test program:
    >
    > use Getopt::Long;
    > GetOptions (
    > "sep:s" => \$sep
    > );
    > #chop($sep = eval "<<__$$__\n$sep\n__$$__");
    > $sep =~ s/(\\[^"\$\@]+)/qq("$1")/eeg;
    > print join $sep, ("line1","line2");


    Make that

    chop($sep = eval "<<__$$\__\n$sep\n__$$\__");
     
    Scott Bass, May 29, 2005
    #11
  12. Scott Bass wrote:

    > "Brian McCauley" <> wrote in message
    > news:d77pkf$473$...
    >
    >>BTW: here's a slightly safer eval based solution

    >
    > I assume that should be "non eval based solution"?


    No, I meant eval() based.

    >> s/(\\[^"\$\@]+)/qq("$1")/eeg;


    The /ee is an eval(). The above can be written:

    s/(\\[^"\$\@]+)/eval qq("$1")/eg;

    > both solutions work a treat. I'll go with the here doc solution; it's an
    > internal, departmental script, and the end user's won't be putting cruft in
    > the command line option.


    OK, but in your internal documentation it's wise to describe it as
    allowing arbitrary Perl.
     
    Brian McCauley, May 29, 2005
    #12
    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. Ajay
    Replies:
    0
    Views:
    538
  2. Ajay
    Replies:
    2
    Views:
    7,378
    Ajay Brar
    Aug 4, 2004
  3. excite
    Replies:
    0
    Views:
    817
    excite
    Nov 2, 2006
  4. hubritic
    Replies:
    1
    Views:
    390
    Piet van Oostrum
    May 27, 2009
  5. Squeamizh
    Replies:
    2
    Views:
    128
    Robert Klemme
    Aug 7, 2006
Loading...

Share This Page