Force interpolation of single quoted character

S

Scott Bass

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
 
S

Shawn Corey

Scott said:
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
 
S

Scott Bass

Shawn Corey said:
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.
 
B

Brian McCauley

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.
 
B

Brian McCauley

Brian said:
the broken form of the obvious answer...


... 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.
 
T

Tad McClellan

Scott Bass said:
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";
 
S

Scott Bass

Tad McClellan said:
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?
 
B

Brian McCauley

Scott said:

[snip Tad ]

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.
 
B

Brian McCauley

Brian said:
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.
 
S

Scott Bass

Brian McCauley said:
Scott said:

[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
 
S

Scott Bass

"Scott Bass" <usenet739_yahoo_com_au> wrote in message

[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__$$\__");
 
B

Brian McCauley

Scott said:
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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,048
Latest member
verona

Latest Threads

Top