http://qs321.pair.com?node_id=652362

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

Dear all,

I must be missing something obvious, but I don't understand why

perl -e 'if ("h@" =~ /(\@)/ ) { print $1 }'

prints the at-sign, but

perl -e 'if ("h@t" =~ /(\@)/ ) { print $1 }'

doesn't.

Thanks,

loris


"It took Loris ten minutes to eat a satsuma . . . twenty minutes to get from one end of his branch to the other . . . and an hour to scratch his bottom. But Slow Loris didn't care. He had a secret . . ." (from "Slow Loris" by Alexis Deacon)

Replies are listed 'Best First'.
Re: Matching @ in string
by lima1 (Curate) on Nov 22, 2007 at 13:22 UTC
    You have introduced the array @t which is interpolated. So you have to quote the @ (or write q{h@t}).
    perl -e 'if ("h\@t" =~ /(\@)/ ) { print $1 }'
    Example for an array interpolation:
    #!/usr/bin/perl use strict; use warnings; my @friends = ('Margaret', 'Richard', 'Carolyn', 'Rohan', 'Cathy', 'Yukiko'); print "Friends: @friends\n";

      OK, so I was missing something obvious.

      But if I don't want to modify the string by escaping the @ and I want to run program as a one-liner, how do I do it if I can't escape the single quotes as you point out here?

      Thanks,

      loris


      "It took Loris ten minutes to eat a satsuma . . . twenty minutes to get from one end of his branch to the other . . . and an hour to scratch his bottom. But Slow Loris didn't care. He had a secret . . ." (from "Slow Loris" by Alexis Deacon)
        ... don't want to modify the string by escaping the @ and I want to run program as a one-liner, how do I do it if I can't escape the single quotes

        Try: ...

        perl -e "print 'h@t'=~ /\@/g"
        or even
        echo 'h@t' | perl -ne 'print /\@/g'

        ... depending on the type of problem you are about to solve.

        Regards

        mwa

Re: Matching @ in string
by dwu (Monk) on Nov 22, 2007 at 13:24 UTC

    I'm suspecting because perl interprets @t within the string h@t as the array @t, since double quotes ("") will cause variables to be interpolated. Inserting both tests into a short script:

    #!/usr/bin/perl use strict; use warnings; if ("h@" =~ /(\@)/ ) { print $1 } if ("h@t" =~ /(\@)/ ) { print $1 }

    produces:

    Possible unintended interpolation of @t in string at ./scratch.pl line + 6. Global symbol "@t" requires explicit package name at ./scratch.pl line + 6. Execution of ./scratch.pl aborted due to compilation errors.

    Doing:

    #!/usr/bin/perl use strict; use warnings; if ('h@' =~ /(\@)/ ) { print $1 } if ('h@t' =~ /(\@)/ ) { print $1 }

    produces:

    @@

    As expected. HTH.

Re: Matching @ in string
by tinita (Parson) on Nov 22, 2007 at 15:40 UTC
    please always use warnings in perl oneliners. i've never understood why people use warnings in their scripts and leave it out in oneliners.
    if i write a oneliner i automatically start it with -wle.
    this has probably saved me lots of time.
    Possible unintended interpolation of @t in string at -e line 1. Name "main::t" used only once: possible typo at -e line 1.

      I am sure this is very good advice, but in the present case

      perl -elw 'if ("h@t" =~ /(\@)/ ) { print $1 }'

      doesn't produce any warning (I'm using 5.8.8 under Cygwin and Debian).

      How did you get the message about the unintended interpolation?

      loris


      "It took Loris ten minutes to eat a satsuma . . . twenty minutes to get from one end of his branch to the other . . . and an hour to scratch his bottom. But Slow Loris didn't care. He had a secret . . ." (from "Slow Loris" by Alexis Deacon)
        perl -elw ...
        i said -wle not -elw =)
        -elw doesn't produce any output.
Re: Matching @ in string
by erroneousBollock (Curate) on Nov 22, 2007 at 13:24 UTC
    perl -e 'if ("h@t" =~ /(\@)/ ) { print $1 }'
    "h@t" looks to Perl like you're trying to interpolate the array @t (the previous case doesn't because the quote ends the string early.

    perl -e 'if ("h\@t" =~ /(\@)/ ) { print $1 }'

    or

    perl -e 'if (\'h@t\' =~ /(\@)/ ) { print $1 }'

    should work fine.

    Update: err, ooops :-)

    -David

      *cough*

      $ perl -e 'if (\'h@t\' =~ /(\@)/ ) { print $1 }' -bash: syntax error near unexpected token `('

      Not sure why - does escaping the single quote not work?

        Because the bash does not change anything in the -e ' .. ' string. And
        if (\'h@t\' =~ /(\@)/ ) {
        is no valid perl.
        And the -e string ends after if (\.