CGI/Perl Guide | Learning Center | Forums | Advertise | Login
Site Search: in

  Main Index MAIN
INDEX
Search Posts SEARCH
POSTS
Who's Online WHO'S
ONLINE
Log in LOG
IN

Home: Perl Programming Help: Beginner:
single to double quote conversion

 



FlayedOne
Novice

Jan 26, 2010, 3:46 PM

Post #1 of 16 (2830 views)
single to double quote conversion Can't Post

Hello,

The problem seems really stupid, so either I'm missing something, or... okay, I'm sure I'm missing something.

My CGI script gets some string variables from some PHP/JS/AJAX over which I have no control through POST method. The problem is those variables are meant to be used as a pattern, some text fragment that is meant to replace matches, and a big text that is meant to be searched. Everything works great beside one simple thing - those strings I get are singlequoted, therefore I can't use $n variables. Here is the code:


Code
#!c:\perl\bin\perl.exe -wT  

use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

print header;

my %form;
foreach my $p (param()) {
$form{$p} = param($p);
}

$regexp = $form{"regexp"};
$regexp =~ s/\s+$//g;
$regexp =~ s/\\(\'|\"|\\)/$1/g;

$changeto = $form{"changeto"};
$changeto =~ s/\s+$//g;
$changeto =~ s/\\(\'|\"|\\)/$1/g;



$answer1 = $form{"content"};
$answer1 =~ s/\s+$//g;
$answer1 =~ s/$regexp/<span class=\\\"green\\\">$&<\/span>/g;

print "{\"div1\":\"".$answer1."\"";

$answer2 = $form{"content"};
$answer2 =~ s/\s+$//g;

if($answer2)
{
$answer2 =~ s/($regexp)/<span class=\\\"red\\\">$changeto<\/span>/g;
print ",\"div2\":\"".$answer2."\"";
}
print "}";


How do I convert a singlequoted string to a doublequoted one?


(This post was edited by FlayedOne on Jan 27, 2010, 2:56 AM)


7stud
Enthusiast

Jan 27, 2010, 2:46 AM

Post #2 of 16 (2811 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

Search google for code tags and then post what you have learned.


(This post was edited by 7stud on Jan 27, 2010, 2:57 AM)


FlayedOne
Novice

Jan 27, 2010, 2:55 AM

Post #3 of 16 (2806 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

And how am I supposed to not respond agressively to that?
You were neither helpful nor respectfull in any way. Just because I missed code tags doesn't mean I haven't spent enough time looking for a solution. I'm also starting to belive that there is no real solution.

BTW, I just found a way to make it somewhat work, but it's an unelegant solution, and I can only make it work for a fixed number of $n variables:

I can do something like that:


Code
$one = "$1"; 
$changeto =~ s/\$1/$one/g;



(This post was edited by FlayedOne on Jan 27, 2010, 2:58 AM)


savo
User

Jan 27, 2010, 3:17 AM

Post #4 of 16 (2795 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

Im not sure but are you trying to change $regexp to the same vale but with "" and not ''?

if so



Code
$regexp =~ s/'/"/g, $regexp;


*note the code tags to keep 7stud happy


FlayedOne
Novice

Jan 27, 2010, 3:32 AM

Post #5 of 16 (2792 views)
Re: [savo] single to double quote conversion [In reply to] Can't Post

Thanks for the reply, but the problem isn't so much about quote characters, it's about the string being treated as single quoted(literal) as opposed to double quoted(non-literal).

I want "$n" where n is a number fragments of $changeto to be treated as variables, and not literal string fragments.


(This post was edited by FlayedOne on Jan 27, 2010, 3:32 AM)


FishMonger
Veteran / Moderator

Jan 27, 2010, 5:38 AM

Post #6 of 16 (2781 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

Start by adding these 2 pragmas (which should be in every Perl script).

Code
use strict; 
use warnings;

and remove the -w switch.


Quote

Code
my %form;  
foreach my $p (param()) {
$form{$p} = param($p);
}


That would be better written as:

Code
my %form = Vars;



Quote

Code
print "{\"div1\":\"".$answer1."\"";


Read up on Perl's Quote-Like Operators in `perldoc perlop` to learn how to fix that line.

Don't quote single vars. See: `perldoc -q quoting`


Quote
the problem isn't so much about quote characters, it's about the string being treated as single quoted(literal) as opposed to double quoted(non-literal).

I want "$n" where n is a number fragments of $changeto to be treated as variables, and not literal string fragments.


You need to rephrase that, it doesn't make much sense to me. Please post an example of what you're talking about.

If you need to split a string into separate vars, then use the split function. See: `perldoc -f split`


FlayedOne
Novice

Jan 27, 2010, 5:54 AM

Post #7 of 16 (2778 views)
Re: [FishMonger] single to double quote conversion [In reply to] Can't Post

I did what you said, but beside fixing how the code looks it doesn't change a thing.


Code
   

#!c:\perl\bin\perl.exe -T

use CGI qw(:standard);
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
use strict;
use warnings;

print header;

my %form;
foreach my $p (param()) {
$form{$p} = param($p);
}



my $regexp = $form{"regexp"};
$regexp =~ s/\s+$//g;
$regexp =~ s/\\(\'|\"|\\)/$1/g;

my $changeto = $form{"changeto"};
$changeto =~ s/\s+$//g;
$changeto =~ s/\\(\'|\"|\\)/$1/g;

my $answer1 = $form{"content"};
$answer1 =~ s/\s+$//g;
$answer1 =~ s/$regexp/<span class=\\\"green\\\">$&<\/span>/g;

print '{"div1":"'.$answer1.'"';

my $answer2 = $form{"content"};
$answer2 =~ s/\s+$//g;

if($answer2)
{
$answer2 =~ s/$regexp/<span class=\\\"red\\\">$changeto<\/span>/g;
print ',"div2":"'.$answer2.'"';
}
print "}";



I can't do this:


Code
   my %form = Vars;



because I get an error "word Vars not allowed while strict in use".

Here is an example. Imagine that I get this data, and put them in following variables:

Code
 $regexp = '([a-z]) \\1';    
$content = 'acabxxbxbx axxb a a';
$changeto = '$1';



I don't have any control over those strings. $regexp works great, and finds exactly what I want - "a a", but when doing substitution:

Code
   $answer2 =~ s/$regexp/<span class=\\\"red\\\">$changeto<\/span>/g;

$1 in $changeto is treated like literal text. That is to be expected, but I want to change the way it's treated so that it would be treated as a $1 variable.

Did that make more sense?


(This post was edited by FlayedOne on Jan 27, 2010, 5:56 AM)


FishMonger
Veteran / Moderator

Jan 27, 2010, 6:16 AM

Post #8 of 16 (2768 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

Hmm, it looks like CGI.pm removed the importation of the Vars function from the ':standard' tag. It's now loaded in the ':cgi-lib' tag. So you'd need to do this:

Code
use CGI qw(:standard :cgi-lib);


Personally, I prefer the OO style.

Code
use CGI; 

my $cgi = CGI->new;
my %form = $cgi->Vars;


For the regex problem, read up on the qr operator in the Regexp Quote-Like Operators section of `perldoc perlop`.

Which is:

Quote

Code
qr/STRING/imosx 

A string which is (possibly) interpolated and then compiled as a regular expression. The result may be used as a pattern in a match

$re = qr/$pattern/;
$string =~ /foo${re}bar/; # can be interpolated in other patterns
$string =~ $re; # or used standalone

Options are:

i Do case-insensitive pattern matching.
m Treat string as multiple lines.
o Compile pattern only once.
s Treat string as single line.
x Use extended regular expressions.

The benefit from this is that the pattern is precompiled into an internal representation, and does not need to be recompiled every time a match is attempted. This makes it very efficient to do something like:

foreach $pattern (@pattern_list) {
my $re = qr/$pattern/;
foreach $line (@lines) {
if($line =~ /$re/) {
do_something($line);
}
}
}

See the perlre manpage for additional information on valid syntax for STRING, and for a detailed look at the semantics of regular expressions.




FishMonger
Veteran / Moderator

Jan 27, 2010, 6:23 AM

Post #9 of 16 (2766 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

I would write:

Code
print '{"div1":"'.$answer1.'"';


As:

Code
print qq({"div1":"$answer1");



FlayedOne
Novice

Jan 27, 2010, 7:04 AM

Post #10 of 16 (2761 views)
Re: [FishMonger] single to double quote conversion [In reply to] Can't Post

I changed all the looks stuff, and did this:


Code
 $regexp = qr/$regexp/;


which as I understood you meant. Of course this works well, and supposedly improves my scripts performance by preventing recompiling the string I get into regexp every time a match is attempted, but I can't see how I can solve my problem with qr. Unless I'm still missing something all it does is compile a string into a regexp, but when I'm doing a substitution:

Code
  s/$regexp/$string/g

while $regexp is supposed to be a regexp, and if it's a string it will get compiled to a regexp, but $string is supposed to be a string and not a regexp, and it's $string($changeto in my script) being treated literally that I have troubles with. How can compiling something to a regexp help?


(This post was edited by FlayedOne on Jan 27, 2010, 7:05 AM)


FishMonger
Veteran / Moderator

Jan 27, 2010, 8:33 AM

Post #11 of 16 (2753 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

What is the value of $form{"changeto"} and what do you want it to be when used in the regex?


FlayedOne
Novice

Jan 27, 2010, 8:37 AM

Post #12 of 16 (2751 views)
Re: [FishMonger] single to double quote conversion [In reply to] Can't Post


Code
$form{"changeto"} = '$1'

(treats $1 as characters)


and I want it to be

Code
 $form{"changeto"} = "$1"

(treats $1 as variable)


(This post was edited by FlayedOne on Jan 27, 2010, 8:38 AM)


FishMonger
Veteran / Moderator

Jan 27, 2010, 8:39 AM

Post #13 of 16 (2748 views)
Re: [FlayedOne] single to double quote conversion [In reply to] Can't Post

See: `perldoc eval`

Mastering Regular Expression
http://oreilly.com/catalog/9780596528126


(This post was edited by FishMonger on Jan 27, 2010, 8:41 AM)


FishMonger
Veteran / Moderator

Jan 27, 2010, 8:43 AM

Post #14 of 16 (2746 views)
Re: [FishMonger] single to double quote conversion [In reply to] Can't Post

You also need to look at the regex 'e' modifier.


7stud
Enthusiast

Jan 28, 2010, 1:07 AM

Post #15 of 16 (2707 views)
Re: [FishMonger] single to double quote conversion [In reply to] Can't Post


Code
my $w = 'world'; 
my $str = 'hello $w';

my $result = eval qq{"$str"};
say $result;

--output:--
hello world



That is equivalent to:


Code
my $w = 'world'; 
my $str = 'hello $w';

my $result = eval "\"$str\"";
say $result;


1) Both of perl's quote marks, ('') and ("") as well as q{} and qq{}, are actually operators; they do something to a series of characters, then return a result. The double quote operator does variable interpolations into the specified series of characters. The single quote operator does not, but it does do some other things.

In both cases, the operator has a return value: what I would call an 'internal' string; and the 'internal' string does not have any quote marks around it--it is just a series of characters. If you do this:

my $str = 'hello';
say $str;

The output does not have any quote marks in it. On the contrary, programmers use quote marks in their code to signal perl to do some transformations to a series of characters--but perl doesn't save the quote marks; perl just saves the return value of the quote mark operator.


2) Analyzing this line:


Code
my $result = eval "\"$str\"";


there is a double quoted string(the outer quotes), with some literal quotes inside the string, and a variable. Because perl interpolates variables into a double quoted string(the outer quotes), $str is replaced by the 'internal' string' which is stored in $str (note that replacement would happen whether the literal quotes(\") were present or not).

The outer double quotes are, once again, an operator; and the operator returns a series of characters, which creates another 'internal string', namely the series of characters: "hello $w". The quote marks are part of this 'internal' string because the original string contained literal quote marks, which happened to be the first and last characters of the string. As a result, you are essentially left with something like:

eval <"hello $w">.

3) The literal quotes(\") are necessary because they are the double quote operator, and you want eval() to execute the double quote operator to perform another interpolation into the string.

4) Another way to think about what's happening in the original line:


Code
my $result = eval "\"$str\"";


is that the double quote operator(the outer double quotes) does one pass of interpolation. That creates the internal string:

"hello $w"

where the quote marks are actually the first and last characters of the 'internal' string. Then eval causes the double quote operator to execute, which does another pass of interpolation, and 'world' is substituted in place of $w.

5) You might think that because the double quote operator does a single pass of interpolation, you could just apply the double quote operator twice and forget about eval(). However, I don't think there is a way to do that. If you write:

my $result = ""$str"";

then perl sees two strings: "" and "" with a variable name in the middle (and that will produce an error). You might try this:

qq{qq{$str}}

and that does a little better, in that it doesn't produce an error, but it doesn't succeed in doing two interpolations. Only one interpolation gets performed leaving you with the string:

qq{hello $w}

To get a second pass of interpolation, you need to use eval(). To set things up correctly for eval(), you first need the double quote operator surrounding your original string. Then the double quote operator will do the first pass of interpolation. Secondly, you need some literal quotes inside the string:

"\"$str\""

perl will save that string as:

"$str"

That is, the first and last character of the 'internal' string are quote marks.

Then eval() will execute the double quote operator that it sees, which will cause the double quote operator to perform the second pass of interpolation. The clearest way to write that is:

qq{"$str"}

5) If all that is too confusing, and you don't want to have to think about all that, you can let the Template module do the thinking for you. You do have to learn about the Template interface:


Code
use strict; 
use warnings;
use 5.010;

use Template;

my $w = 'world';
my $str = 'hello $w';

my $vars = {
w => 'world',
};

my $t = Template->new({INTERPOLATE => 1});

my $result;
$t->process(\$str, $vars, \$result) or die $t->error();

say $result;

--output:--
hello world





6) Your problem has nothing to do with CGI, and posting lots of confusing, irrelevant code does nothing to encourage people to help you. In the future, construct a short example that demonstrates your problem and post that. Yes, it takes some time and effort to put your real program aside and come up with an example program that models the problem, but you will learn a lot more doing that--often times solving the problem yourself, and it will make it a lot easier for people to help you if they don't have to wade through a bunch of confusing code.


(This post was edited by 7stud on Jan 29, 2010, 12:17 AM)


FlayedOne
Novice

Jan 28, 2010, 11:56 PM

Post #16 of 16 (2661 views)
Re: [7stud] single to double quote conversion [In reply to] Can't Post

Thanks for your help guys, eval is really the function I was looking for, not to mention that it looks like my code is much more in perl style now.

I had a problem with taint mode which I had to turn off, and now my script works perfectly. I get a feeling I should've handled it differently though, so I'm gonna read up more on taint.

Thanks;).

 
 


Search for (options) Powered by Gossamer Forum v.1.2.0

Web Applications & Managed Hosting Powered by Gossamer Threads
Visit our Mailing List Archives