[PATTERN MATCHING]

Discussion in 'Perl Misc' started by Nicolas Vautier, Dec 17, 2004.

  1. Hey guys,

    Let's say that I have this:

    $line =~ s/$pattern/$replacement/;

    It should find every $pattern in $line and replace it by $replacement
    right?

    But since I have characters such as "|", """, "'", "!", "?" in my
    strings, it has a very strange behavior.

    Is there any way to specify perl NOT TO USE regular expressions in my
    example?

    Thanks for your help,
    Nico
    Nicolas Vautier, Dec 17, 2004
    #1
    1. Advertising

  2. At 2004-12-17 02:14PM, Nicolas Vautier <> wrote:
    > Let's say that I have this:
    >
    > $line =~ s/$pattern/$replacement/;
    >
    > It should find every $pattern in $line and replace it by $replacement
    > right?
    >
    > But since I have characters such as "|", """, "'", "!", "?" in my
    > strings, it has a very strange behavior.
    >
    > Is there any way to specify perl NOT TO USE regular expressions in my
    > example?


    perldoc -f quotemeta

    $line =~ s/\Q$pattern/$replacement';


    --
    Glenn Jackman
    Glenn Jackman, Dec 17, 2004
    #2
    1. Advertising

  3. "Nicolas Vautier" <> wrote in
    news::

    Subject: [PATTERN MATCHING]

    Please don't shout.

    > Let's say that I have this:
    >
    > $line =~ s/$pattern/$replacement/;
    >
    > It should find every $pattern in $line and replace it by $replacement
    > right?
    >
    > But since I have characters such as "|", """, "'", "!", "?" in my
    > strings, it has a very strange behavior.


    See

    perldoc perlop


    > Is there any way to specify perl NOT TO USE regular expressions in my
    > example?


    Sure you could do search and replace without regular expressions but it
    would be very tedious and bug prone. Why do you want to do that?

    Sinan
    A. Sinan Unur, Dec 17, 2004
    #3
  4. Nicolas  Vautier

    Juha Laiho Guest

    "Nicolas Vautier" <> said:
    >Let's say that I have this:
    >
    >$line =~ s/$pattern/$replacement/;
    >
    >It should find every $pattern in $line and replace it by $replacement
    >right?
    >
    >But since I have characters such as "|", """, "'", "!", "?" in my
    >strings, it has a very strange behavior.
    >
    >Is there any way to specify perl NOT TO USE regular expressions in my
    >example?


    I think you're after \Q and \E - as in

    $line =~ s/\Q$pattern\E/$replacement/;

    See 'perldoc perlre' for explanation.
    --
    Wolf a.k.a. Juha Laiho Espoo, Finland
    (GC 3.0) GIT d- s+: a C++ ULSH++++$ P++@ L+++ E- W+$@ N++ !K w !O !M V
    PS(+) PE Y+ PGP(+) t- 5 !X R !tv b+ !DI D G e+ h---- r+++ y++++
    "...cancel my subscription to the resurrection!" (Jim Morrison)
    Juha Laiho, Dec 17, 2004
    #4
  5. Nicolas  Vautier

    niko Guest

    That's exactly what I want to do.
    Not using regular expressions.
    Because in the example, when $pattern="super.test?\nothin" and
    $replacement="another?greatte\st", it obviously doesn't work properly.
    Thanks for your reply,
    Nico
    niko, Dec 17, 2004
    #5
  6. Nicolas  Vautier

    niko Guest

    > > Is there any way to specify perl NOT TO USE regular expressions in
    my
    > > example?

    >
    > Sure you could do search and replace without regular expressions but

    it
    > would be very tedious and bug prone. Why do you want to do that?
    >


    Because my two strings contain characters used in regular expressions
    such as ?.|\ ...
    What could make perl considering those characters as characters like
    others?

    Thx,
    Nico
    niko, Dec 17, 2004
    #6
  7. "niko" <> wrote in news:1103312160.501287.309130
    @f14g2000cwb.googlegroups.com:

    > That's exactly what I want to do.
    > Not using regular expressions.
    > Because in the example, when $pattern="super.test?\nothin" and
    > $replacement="another?greatte\st", it obviously doesn't work properly.


    No, it looks like what you want to do is keep using regular expressions but
    have some special characters not be special.

    Based on your problem description, I am not sure you want those double-
    quotes in

    my $pattern="super.test?\nothin";

    either.

    Please do read

    perldoc perlop

    Sinan
    A. Sinan Unur, Dec 17, 2004
    #7
  8. Nicolas Vautier wrote:
    > Let's say that I have this:
    >
    > $line =~ s/$pattern/$replacement/;
    >
    > It should find every $pattern in $line and replace it by $replacement
    > right?


    No, it should find *the first occurrence of* $pattern in $line and
    replace it. You need the /g modifier to replace *every* of something.

    > But since I have characters such as "|", """, "'", "!", "?" in my
    > strings, it has a very strange behavior.
    >
    > Is there any way to specify perl NOT TO USE regular expressions in my
    > example?


    Others have pointed you to this solution:

    $line =~ s/\Q$pattern/$replacement/;

    which makes the left side of the s/// operator treat $pattern as a
    string. OTOH, using the regex engine for searching and replacing strings
    is not very efficient, and a combination of the substr() and index()
    functions can be used instead:

    substr $line, index($line, $pattern), length $pattern, $replacement;

    If you actually need multiple substitutions, this would work:

    {
    local $[ = 1;
    while ( my $pos = index $line, $pattern ) {
    substr $line, $pos, length $pattern, $replacement;
    }
    }

    See "perldoc -f substr" and "perldoc -f index".

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 17, 2004
    #8
  9. A. Sinan Unur wrote:
    > Nicolas Vautier wrote:
    >>Is there any way to specify perl NOT TO USE regular expressions in my
    >>example?

    >
    > Sure you could do search and replace without regular expressions but it
    > would be very tedious and bug prone.


    In what way would searching and replacing *strings* without the regex
    engine be "tedious and bug prone"?

    See my other post in this thread.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 17, 2004
    #9
  10. Gunnar Hjalmarsson <> wrote in
    news::

    > A. Sinan Unur wrote:
    >> Nicolas Vautier wrote:
    >>>Is there any way to specify perl NOT TO USE regular expressions in my
    >>>example?

    >>
    >> Sure you could do search and replace without regular expressions but it
    >> would be very tedious and bug prone.

    >
    > In what way would searching and replacing *strings* without the regex
    > engine be "tedious and bug prone"?


    Well, I thought of posting a similar routine for the purposes of this
    question but then decided against it. While that method works for the
    specific case we are talking about, it becomes unwieldy very fast the
    moment you introduce even the simplest pattern matching features we take
    for granted.

    I did not mean to imply, although it does come across that way, that
    searching and replacing plain strings is that hard.

    However, if you do want an example of a bug with the code you posted:

    #! perl

    use strict;
    use warnings;

    my $text = q{I would like to replace Gunnar's name with my name.};

    my $search = 'Tad';
    my $replace = 'Sinan';

    substr $text, index($text, $search), length $search, $replace;

    print $text;

    __END__

    D:\Home>perl s.pl
    I would like to replace Gunnar's name with my nameSinan

    I know, I know, it is a cheap shot :) But it is a bug nevertheless. You do
    need to remember to check if the match actually succeeded.

    Sinan.
    A. Sinan Unur, Dec 17, 2004
    #10
  11. Gunnar Hjalmarsson <> wrote in
    news::

    > If you actually need multiple substitutions, this would work:
    >
    > {
    > local $[ = 1;
    > while ( my $pos = index $line, $pattern ) {
    > substr $line, $pos, length $pattern, $replacement;
    > }
    > }


    Opps. I did not read this far down in my reply to your other message.
    Apologies.

    Sinan.
    A. Sinan Unur, Dec 17, 2004
    #11
  12. "A. Sinan Unur" <> wrote in
    news:Xns95C2A48112B89asu1cornelledu@132.236.56.8:

    > Gunnar Hjalmarsson <> wrote in
    > news::
    >
    >> If you actually need multiple substitutions, this would work:
    >>
    >> {
    >> local $[ = 1;
    >> while ( my $pos = index $line, $pattern ) {
    >> substr $line, $pos, length $pattern, $replacement;
    >> }
    >> }

    >
    > Opps. I did not read this far down in my reply to your other message.
    > Apologies.


    On second thought, another cheap shot:

    #! perl

    use strict;
    use warnings;

    my $line = 'Sinan';
    my $pattern = 'Sinan';
    my $replacement = 'A. Sinan Unur';

    {
    local $[ = 1;
    while ( my $pos = index $line, $pattern ) {
    substr $line, $pos, length $pattern, $replacement;

    }
    }

    print $line;

    __END__


    Sinan
    A. Sinan Unur, Dec 17, 2004
    #12
  13. A. Sinan Unur wrote:
    > However, if you do want an example of a bug with the code you posted:
    >
    > #! perl
    >
    > use strict;
    > use warnings;
    >
    > my $text = q{I would like to replace Gunnar's name with my name.};
    >
    > my $search = 'Tad';
    > my $replace = 'Sinan';
    >
    > substr $text, index($text, $search), length $search, $replace;
    >
    > print $text;
    >
    > __END__
    >
    > D:\Home>perl s.pl
    > I would like to replace Gunnar's name with my nameSinan
    >
    > I know, I know, it is a cheap shot :)


    Not cheap at all. The single substitution variant should better be
    something like:

    if ( ( my $pos = index $line, $pattern ) >= 0 ) {
    substr $line, $pos, length $pattern, $replacement;
    }

    Thanks for pointing it out!

    Btw, the multiple substitution should be:

    while ( ( my $pos = index $line, $pattern ) >= 0 ) {
    substr $line, $pos, length $pattern, $replacement;
    }

    to prevent the need to fiddle with the $[ variable.

    > But it is a bug nevertheless. You do
    > need to remember to check if the match actually succeeded.


    Yep.

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 17, 2004
    #13
  14. A. Sinan Unur wrote:
    > On second thought, another cheap shot:
    >
    > #! perl
    >
    > use strict;
    > use warnings;
    >
    > my $line = 'Sinan';
    > my $pattern = 'Sinan';
    > my $replacement = 'A. Sinan Unur';
    >
    > {
    > local $[ = 1;
    > while ( my $pos = index $line, $pattern ) {
    > substr $line, $pos, length $pattern, $replacement;
    >
    > }
    > }
    >
    > print $line;
    >
    > __END__


    Yeah, *that* was cheap. :) Well, I never said you don't need to be
    attentive to what you are doing when playing with substr() and index().
    Just that it may be more efficient...

    --
    Gunnar Hjalmarsson
    Email: http://www.gunnar.cc/cgi-bin/contact.pl
    Gunnar Hjalmarsson, Dec 17, 2004
    #14
  15. Gunnar Hjalmarsson <> wrote in
    news::

    > A. Sinan Unur wrote:
    >> On second thought, another cheap shot:


    ....

    > Yeah, *that* was cheap. :)


    ....

    I know, I know.

    > Well, I never said you don't need to be attentive to what you are doing
    > when playing with substr() and index(). Just that it may be more
    > efficient...


    Mine was just an indirect way of trying to fix the OP's terminology and
    also guide him toward a document which he should benefit from by reading in
    its entirety.

    I suspect that the OP's problem may involve inappropriate (or
    inconsistent) use of double quotes as well as failing to quote the regex-
    special characters, but this is just a suspicion since the OP did not show
    real code and real data.

    I did originally think about posting an index/substr based solution but too
    many special cases kept pop up in my mind. Then I remembered Sedgewick's
    treatment of search and replace in C, and I gave up.

    Hope you had fun. I did :)

    Sinan.
    A. Sinan Unur, Dec 17, 2004
    #15
  16. Nicolas  Vautier

    Guest

    Nicolas Vautier wrote:
    >
    > Let's say that I have this:
    >
    > $line =~ s/$pattern/$replacement/;
    >
    > It should find every $pattern in $line and replace it by $replacement
    > right?


    No. It will replace only the first occurrence of $pattern (if at
    least one exists) with $replacement. To replace every occurrence, use
    the /g switch, like this:

    $line =~ s/$pattern/$replacement/g;

    > But since I have characters such as "|", """, "'", "!", "?" in my
    > strings, it has a very strange behavior.
    >
    > Is there any way to specify perl NOT TO USE regular expressions in my
    > example?


    Yes. Others posters have (correctly) said:

    $line =~ s/\Q$pattern\E/$replacement/;

    but you can also "backslash" the special characters (like "|", """,
    "'", "!", "?") with the quotemeta() function. This function will
    return a new pattern that you can use that has all the special
    characters escaped (so that they won't interfere with the regular
    expression matching). You use it like this:

    my $escapedPattern = quotemeta($pattern);
    $line =~ s/$escapedPattern/$replacement/g;

    In other words, if you have the line:

    print quotemeta("Again? (y/n)");

    you'll see the output:

    Again\?\ \(y\/n\)

    meaning that if you use that output in a pattern match, the "?", "(",
    and ")" characters won't affect how you match a pattern.

    Note that, according to "perldoc -f quotemeta", the line:

    my $escapedPattern = quotemeta($pattern);

    is equivalent to:

    my $escapedPattern = "\Q$pattern\E";

    which makes the following regular expression substitutions equivalent:

    my $escapedPattern = quotemeta($pattern);
    $line =~ s/$escapedPattern/$replacement/g;

    $line =~ s/\Q$pattern\E/$replacement/g;

    Which method should you use? In my opinion, you should use
    whichever one you find more readable and easier to understand. And of
    course, that part depends on you.
    I hope this helps, Nicolas.

    -- Jean-Luc
    , Dec 19, 2004
    #16
    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. DelphiDude
    Replies:
    3
    Views:
    1,161
  2. danpres2k
    Replies:
    3
    Views:
    7,458
    danpres2k
    Aug 25, 2003
  3. CV
    Replies:
    2
    Views:
    584
    Charles DeRykus
    Aug 31, 2004
  4. Marc Bissonnette

    Pattern matching : not matching problem

    Marc Bissonnette, Jan 8, 2004, in forum: Perl Misc
    Replies:
    9
    Views:
    221
    Marc Bissonnette
    Jan 13, 2004
  5. Bobby Chamness
    Replies:
    2
    Views:
    215
    Xicheng Jia
    May 3, 2007
Loading...

Share This Page