xyzzy has asked for the wisdom of the Perl Monks concerning the following question:

How exactly does the choice of delimiter affect whether or not a regex will work (in the way intended)?
I decided to use ActivePerl to do edit a bunch of SQL saved in a text file:
perl -p -e "s/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as $2/" temp.txt
did not match

perl -p -e "s|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as $2|" temp.txt
did match.
???

Replies are listed 'Best First'.
Re: Choosing regex delimiters
by jethro (Monsignor) on Feb 06, 2009 at 16:37 UTC

    I changed the double-quotes to single-quotes and got a reasonable result. Which to me suggests that the shell does some processing with double-quoted strings before it reaches perl

    Whatever shell you are using, try this:

    > echo 'hello $1' hello $1 > echo "hello $1" hello
      Which to me suggests that the shell does some processing with double-quoted strings before it reaches perl
      That depends on the shell. Typically, Unix shells with do interpolation (including `` expanding) inside double quoted strings, and no interpolation inside single quoted string.

      It's my understanding that you only have double quoted strings on most Windows shells (not counting shells that started life on Unix, then got ported). No idea whether they do interpolation or not.

        Naturally. Not knowing the shell he uses I gave him a pointer where to look. Probably should have said 'my shell' instead of 'the shell'.

        Whatever shell he is using, there should be a mechanism to avoid interpolation, often single quotes or generous use of backward slashes. Do backward slashes work on windows? I never checked.

Re: Choosing regex delimiters
by Not_a_Number (Prior) on Feb 06, 2009 at 18:47 UTC

    Both versions work fine for me on XP Pro with Perl v5.8.8...

    Update: Added output

    C:\progs\perl>perl -p -e "s/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as +$2/" temp. txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar iif([month]>,[01-estimate].apr,0) as apr C:\progs\perl>perl -p -e "s|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as +$2|" temp. txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar iif([month]>,[01-estimate].apr,0) as apr C:\progs\perl>perl -v This is perl, v5.8.8 built for MSWin32-x86-multi-thread (with 12 registered patches, see perl -V for more detail)
Re: Choosing regex delimiters
by hbm (Hermit) on Feb 06, 2009 at 16:42 UTC
    Can you provide sample data? They work the same for me with a dummy string (after I change "as $1" in the second):
    $_ = "adfjdk.kkk,8888888"; s/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as $2/; print "$_\n"; $_ = "adfjdk.kkk,8888888"; s|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as $2|; print "$_\n"; # prints: # iif([month]>,adfjdk.kkk,0) as kkk8888888 # iif([month]>,adfjdk.kkk,0) as kkk8888888

    Update: Isn't the orginal question essentially, Why does s/// differ from s|||, all other things being equal? (And I doubt the claim.) But the other responses looked at quotes, which were identical in both expressions. Am I missing the point? OP, can you provide working examples that illustrate the problem?

      [01-estimate].jan, [01-estimate].feb, [01-estimate].mar, [01-estimate].apr, (etc...)
      This is on Windows XP using ActivePerl EE 5.8.6. Using s/// makes no substitutions, using s||| works as expected. Is this something specific to the XP command line?

        No surprises, I get the wrong results with double-quotes and the correct results with single-quotes; and identical results in each case, whether delimiting with / or |.

        $ perl -p -e "s/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as $2/" z.txt iif([month]>,.,0) as iif([month]>,.,0) as iif([month]>,.,0) as $ perl -p -e "s|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as $2|" z.txt iif([month]>,.,0) as iif([month]>,.,0) as iif([month]>,.,0) as $ perl -p -e 's|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as $2|' z.txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar $ perl -p -e 's/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as $2/' z.txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar

        It should and does work fine in XP's cmd shell.

        >perl -p -e "s|(.*?)\.(\w\w\w),|iif([month]>,$1.$2,0) as $2|" temp.txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar iif([month]>,[01-estimate].apr,0) as apr >perl -p -e "s/(.*?)\.(\w\w\w),/iif([month]>,$1.$2,0) as $2/" temp.txt iif([month]>,[01-estimate].jan,0) as jan iif([month]>,[01-estimate].feb,0) as feb iif([month]>,[01-estimate].mar,0) as mar iif([month]>,[01-estimate].apr,0) as apr

        Tested with with ActivePerl 5.6.0, 5.6.1, 5.8.0, 5.8.8, 5.10.0

Re: Choosing regex delimiters
by Anonymous Monk on Feb 06, 2009 at 16:47 UTC
    It doesn't unless variable interpolation is involved (s/// is like "", but s''' is like ""), but your regexes aren't equivalent(you fixed typo).
    D:\>perl $bar = 1; $_ = 123; s/$bar/bar said $bar -/; print __END__ bar said 1 -23 D:\> D:\> D:\>perl $bar = 1; $_ = 123; s'$bar'bar said $bar -'; print __END__ 123 D:\>perl $bar = 1; $_ = 123; s'1'bar said $bar -'; print __END__ bar said $bar -23 D:\>
    To see if the shell does interpolation, use B::Deparse, ex perl -MO=Deparse ...
Re: Choosing regex delimiters
by Bloodnok (Vicar) on Feb 06, 2009 at 20:23 UTC
    To answer your first question, I almost always use comma delimited regexes, in that way it's second nature for me to write eminently (IMO) readable regex's manipulating strings containing slashes (/) ... only resorting to the more usual slash delimiter iff I need the regex to handle commas. Thus, using commas, I don't have to remember to escape slashes in the regex itself.

    Maybe I've been lucky thus far ... AFAIR I've never had occasion to process strings whereby both slashes and commas were of importance :-)

    Just my 2 penn'orth...

    A user level that continues to overstate my experience :-))