String parsed wrong by perl

A

A. Farber

Hi,

I've got a string in my bigger program that parses wrong.
I've prepared a one-liner which shows the problem:

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/
color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

$ perl -v
This is perl, v5.8.8 built for i386-openbsd

As a workaround I have to split the string:

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}} . qq
{[/color:$self->{BBCODE}]}'
[color=#FF0000:][/color:]

Any comments? I haven't seen this happen often

Regards
Alex
 
A

A. Sinan Unur

I've got a string in my bigger program that parses wrong.
I've prepared a one-liner which shows the problem:

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/
color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

Can you explain, in words, what should be printed by the statement
above?
Any comments?

This is not the way to interpolate elements pointed to by hash
references into strings.
I haven't seen this happen often

I don't know what *this* is but I am indeed saddened to see code like
above and I do hope it is rare.

(s)sprintf would help.

So would a proper templating system.

Sinan

--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
A

A. Farber

This is not the way to interpolate elements pointed to by hash
references into strings.

$ perl -e '$href={a,1}; print "$href->{a}\n";'
1

$ perl -v

This is perl, v5.8.8 built for i386-openbsd

Regards
Alex
 
J

Jens Thoms Toerring

A. Farber said:
I've got a string in my bigger program that parses wrong.
I've prepared a one-liner which shows the problem:
$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

What do you expect? With 'qq' you tell that the string is to be
interpolated. Then you have somewhere in the string

$card->{HTML}[/color:$self->{BBCODE}]

Now, apart from not having a hash reference called '$card' anywhere
in scope you try to tread

$card->{HTML}

as an array (reference), due to the following '['. And as the array
index you have

/color:$self->{BBCODE}

which only makes sense as a regexp, due to the leading '/'.
But since there's no trailing '/' you get told that the
search pattern is not terminated.
$ perl -v
This is perl, v5.8.8 built for i386-openbsd
As a workaround I have to split the string:
$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}} . qq
{[/color:$self->{BBCODE}]}'
[color=#FF0000:][/color:]

That works because you avoid '$card->{HTML}' being seen as an
array (reference).

Another way around that would be to write

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}\[/color:$self->{BBCODE}]}'

since then the '[' following '$card->{HTML}' can't be mistaken
to be an access of an array element.

But, please, why do would use such a horrible mess at all?

Regards, Jens
 
P

Peter Makholm

A. Farber said:
Hi,

I've got a string in my bigger program that parses wrong.
I've prepared a one-liner which shows the problem:

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/
color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

What happes is that perl assumes that you want to access $card as it
is an hash of arrays (or at least that $card->{HTML} is an arrayref).

To do this it has to parse '/color:$self->{BBCODE}' as an expression
into this array. And this is clearly an unterminated search pattern.

//Makholm
 
J

Jens Thoms Toerring

$ perl -e '$href={a,1}; print "$href->{a}\n";'
1

What do you mean by that? The result looks pretty fine and
to be expected. Don't you think so? And in your original post
you where using something that looked more like this

$ perl -e '$href={a,(1,2,3)}; print "$href->{a}[0]\n";'
1

but with some invalid expression instead of '0' as the array
index (and $href never defined).

Regards, Jens
 
A

A. Farber

Hello,

A. Farber said:
$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

What do you expect? With 'qq' you tell that the string is to be
interpolated. Then you have somewhere in the string

$card->{HTML}[/color:$self->{BBCODE}]

Now, apart from not having a hash reference called '$card' anywhere
in scope you try to tread

Yes it's missing in the oneliner, but I obviously have
the $card in scope in my program, so this doesn't matter.
$card->{HTML}

as an array (reference), due to the following '['. And as the array
index you have

Yes, that is it - thanks for explanation.
But, please, why do would use such a horrible mess at all?

I'm surprised why people jump at my code,
I don't think it's that horrible.

I'm just trying to list cards of red and black
suits in a post of a phpBB3-forum, like here:
http://preferans.de/viewtopic.php?f=5&t=9

If phpBB3 has decided to code font colors by
[color=#FF0000:random]blah[/color:random]
then it isn't my fault, isn't it?

And the suggested usage of sprintf wouldn't help anything.
For me "$href->{x}: $href->{y}, $href->{z}"
is not less readable than
sprintf "%s: %s, %s", $href->{x}, $href->{y}, $href->{z};

Regards
Alex
 
A

A. Farber

What do you mean by that?

I mean by that that "A. Sinan Unur" is wrong when saying
"This is not the way to interpolate elements pointed to by hash
references into strings."

Regards
Alex
 
A

A. Farber

Hello Peter,

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/
color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

What happens is that perl assumes that you want to access $card as it
is an hash of arrays (or at least that $card->{HTML} is an arrayref).

To do this it has to parse '/color:$self->{BBCODE}' as an expression
into this array. And this is clearly an unterminated search pattern.

yes, thanks. Now I understand it was parsing
it as an array index (I missed that before).

I'm just still a bit surprised, that perl tries
to parse a regex from inside of a string...
It never parses "xxx/blah/xxx" doesn't it?

Regards
Alex
 
T

Tad J McClellan

A. Farber said:
$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/color:$self->{BBCODE}]}'
But, please, why do would use such a horrible mess at all?

I'm surprised why people jump at my code,
I don't think it's that horrible.


It is horrible for maintenance.

When debugging code you are often looking for uses of variables.

Having uses of variables embedded between loads of (necessarily)
homely data makes them harder to find.

If phpBB3 has decided to code font colors by
[color=#FF0000:random]blah[/color:random]
then it isn't my fault, isn't it?


Of course not, but that is the data.

The complaints are about the code, not about the data.

The ugliness of the data cannot be controlled by the programmer,
the ugliness of the code can be.

And the suggested usage of sprintf wouldn't help anything.
For me "$href->{x}: $href->{y}, $href->{z}"
^^ ^^
^^ ^^
is not less readable than
sprintf "%s: %s, %s", $href->{x}, $href->{y}, $href->{z};


That is because there are only 4 characters of data in your
contrived example, while there are 25 characters of data
in your real code.

[color=#FF0000:%s]%s[/color:%s]
^^^^^^^^^^^^^^^ ^ ^^^^^^^^ ^
^^^^^^^^^^^^^^^ ^ ^^^^^^^^ ^

Finding a needle next to a stalk of hay is easier than finding
a needle in a haystack. :)

printf makes it easy to see the variables that are used in the statement:

printf '[color=#FF0000:%s]%s[/color:%s]',
$self->{BBCODE}, $card->{HTML}, $self->{BBCODE};
 
T

Tad J McClellan

A. Farber said:
Hello Peter,

$ perl -e 'print qq{[color=#FF0000:$self->{BBCODE}]$card->{HTML}[/
color:$self->{BBCODE}]}'
Search pattern not terminated at -e line 1.

What happens is that perl assumes that you want to access $card as it
is an hash of arrays (or at least that $card->{HTML} is an arrayref).

To do this it has to parse '/color:$self->{BBCODE}' as an expression
into this array. And this is clearly an unterminated search pattern.

yes, thanks. Now I understand it was parsing
it as an array index (I missed that before).

I'm just still a bit surprised, that perl tries
^^^^^^^^^^^^^^^

Note that if you had used printf(), you would not have been surprised.

The surprise results from interpolation.

If there is no interpolation, there is no surprise!

to parse a regex from inside of a string...


It doesn't.

It tries to parse expressions that appear in subscripts though.

$_ = $some_array[/color:$self->{BBCODE}];

has the same syntax error as

$_ = "$some_array[/color:$self->{BBCODE}]";

does.

Would you be surprised by a syntax error in that first one? Probably not.

It never parses "xxx/blah/xxx" doesn't it?


No, because that is merely a string, there are no subscripts that
need to be evaluated in order to complete interpolation.
 
A

A. Sinan Unur

I mean by that that "A. Sinan Unur" is wrong when saying
"This is not the way to interpolate elements pointed to by hash
references into strings."

You are missing the point.

I did not say you cannot interpolate this way.

While your simple example clearly works, things get very hairy very
quickly as your question shows.

You can fit a square peg in a round hole but why do it?

Use (s)printf or a proper templating system.

Sinan
--
A. Sinan Unur <[email protected]>
(remove .invalid and reverse each component for email address)

comp.lang.perl.misc guidelines on the WWW:
http://www.rehabitation.com/clpmisc/
 
A

A. Farber

Finding a needle next to a stalk of hay is easier than finding
a needle in a haystack.  :)

printf makes it easy to see the variables that are used in the statement:

    printf '[color=#FF0000:%s]%s[/color:%s]',
           $self->{BBCODE}, $card->{HTML}, $self->{BBCODE};

:) Ok, maybe sprintf is better

Thanks
 
I

Ilya Zakharevich

I'm just still a bit surprised, that perl tries
to parse a regex from inside of a string...

It is not "inside of string". Some parts of double-quoted regions are
STRINGS, some are CODE. E.g.
perl -wle "qq(abc) =~ /(.)(.)(.)/; print qq(${1+2})"
c

Likewise for $a
Code:
, $a{CODE}, and @a[CODE], @a{CODE}; modify for ->
accordingly...  One can avoid this by backwacking $, {, [, or -.

Hope this helps,
Ilya
 
S

sln

I'm just still a bit surprised, that perl tries
to parse a regex from inside of a string...

It is not "inside of string". Some parts of double-quoted regions are
STRINGS, some are CODE. E.g.
perl -wle "qq(abc) =~ /(.)(.)(.)/; print qq(${1+2})"
c

Likewise for $a
Code:
, $a{CODE}, and @a[CODE], @a{CODE}; modify for ->
accordingly...  One can avoid this by backwacking $, {, [, or -. ^^^^^^^^^^^

Hope this helps,
Ilya[/QUOTE]

Whoa, now there's a technical term "backwacking".
What the hell does that mean?

Is that like itchy finger hoosamacalla?

Unfortunately, I've seen this term before but never, ever, would would give
creadence to its existence as legitimate phrase used to technically describe
anything, nor validate it's legitimacy.

-sln
 

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,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top