in reply to passing qr//'d regexp via Perl/Tk Entry widget

I ran your code, and it behaves as I would expect. If I type in "barbaz$" or "oob" and hit the $go_button, I get a match, and if I type "foot" or "xyz", I don't get a match. Isn't this exactly what you want?

I am guessing you think the input text has to be wrapped in a qr// for it to work, but that's not the case. You only need to feed a regular-expression string to m//, not a regular-expression object (which you construct with qr//), In fact, since qr// is really just a chunk of perl code, you would need to eval it to get it to work. Replacing the last line of your command sub for $go_button with the following would force users to enter their regular expression using qr//:
$string =~ eval $exp ? print STDOUT "match!\n" : print STDOUT "No matc +h!\n";
It is only by chance that (?-xism:foo) matches "foobarbaz" - it has nothing to do with the fact that this is the string representation of the regular expression qr/foo/. The "(?-xism:" signals the start of a non-capturing grouping with the x, i, s and m modifiers turned off. This little construct is buried within perlre. I can't say I ever realized that the stringification of a regular expression is itself another related, similar regular expression.

Update: Boy do I feel like a fool! Whenever Perl printed (?-xism:the regex), I always read it as "Regular expression-ism: 'the regex'". As in "The United States' policy was one of protectionism". I never realized Perl was being helpful and showing me the modifiers it was (or wasn't) using.

Replies are listed 'Best First'.
Re^2: passing qr//'d regexp via Perl/Tk Entry widget
by young_stu (Beadle) on Jun 23, 2005 at 23:13 UTC
    I guess I need to clarify why the behavior of this script puzzles me, and say a bit more about what I ulimately want to do:

    This script puzzles me because if I wrote:
    my $string = "foobarbaz"; my $exp = qr/foo/; print STDOUT "matching $exp...\n"; print STDOUT "match!\n" if $string =~ m/$exp/;
    I would get what I expect...i.e. I would see:
    matching (?-xism:foo)... match!
    But when the regexp object qr/foo/ is instead assigned to the variable $exp via the get method, it (seems) to cease to be a regexp object. In fact, it seems to become the string literal 'qr/foo/'. So what is the get method doing to my regexp object and how can I make it stop?

    The other thing is that I want the user to have the _choice_ to pass a regexp in a qr//, in double quoted string, or in single quoted string, as he or she sees fit given the context. There's good reason for this. For instance, many users may not know that they can pass modifiers (say /s) via the "(?:s foo)" "span" operator, but may know that they can get the same effect by writing qr/foo/s. In otherwords, I want it to be true that my Perl/Tk app allows "more than one way to do it." Otherwise "requiring" users to enter, say, everthing as a qr// object would be ok.

    Thanks!
      But when the regexp object qr/foo/ is instead assigned to the variable $exp via the get method, it (seems) to cease to be a regexp object. In fact, it seems to become the string literal 'qr/foo/'. So what is the get method doing to my regexp object and how can I make it stop?
      You're hitting the nail on the head, but not seeing it, I think. When you type "qr/foo/" into your entry widget, it is just a string. It never "ceases" to be a regular expression object - it never was one. You might have typed anything into your text box, a limmerick or a dirty word or anything. Just because the text is "qr/foo/", and happens to be a string that stands for a regular expression object in the Perl language is immaterial. The program won't look at the text and say, aha, this is a perl construct. It's just text.

      This is completely different from writing my $exp = qr/foo/; in your perl script. This is part of your program (and not your program input), and perl knows how to parse this. If, instead of my $exp = qr/foo/; you wrote my $exp = "qr/foo/";, you would get the same behavior as when the regex is passed via your text entry widget.

      If you want Perl to parse and interpret the entered text as a chunk of Perl code, you need to use the string version of eval. That tells perl that the text passed in is more than text, and to evaluate it as a Perl expression. I hope this makes sense.

      As for allowing a user several ways to pass a regular expression, you should read the text entered and adjust your processing accordingly, like [id://injunjoel] suggests. Something like this (completely untested):
      my $regexp = undef; my $entered_text = $regexp_entry -> get(); if ($entered_text =~ m!^qr/!){ # User has passed a "qr//" type regex: $regexp = eval $entered_text; } else{ # User has passed a straight regular expression $regexp = m/$entered_text/; }
      Note that there is no need in the "else" branch for the user to have enclosed their code in single- or double-quotes. You are reading text from the widget, then using that text to construct a regular expression at run time.

        That's extremely helpful. Answers my questions exactly.

        thanks very much.