Beefy Boxes and Bandwidth Generously Provided by pair Networks
Keep It Simple, Stupid
 
PerlMonks  

$1[

by rsFalse (Chaplain)
on Oct 10, 2017 at 19:35 UTC ( [id://1201114]=perlquestion: print w/replies, xml ) Need Help??

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

Hello.

I was trying to convert parentheses to square brackets in my program:
#!/usr/bin/perl use warnings; use strict; $\ = $/; $_ = reverse "(a+b)*c"; # or some longer sequence s/\)([^()]+)\(/]$1[/g; print scalar reverse y/][/)(/r;
OUTPUT:
syntax error at ./bracket.pl line 13, near "y/][/)(/r;" Execution of ./bracket.pl aborted due to compilation errors.
I guess that perl tried to interpret $1[ as element of an array @1? So I solved this problem in two ways, using:
s/\)([^()]+)\(/]$1\[/g; # '[' is not a metachar here
and usual way
s/\)([^()]+)\(/]${1}[/g; # to surround the whole variable name which is interpreted inside a st +ring

Replies are listed 'Best First'.
Re: $1[
by kennethk (Abbot) on Oct 10, 2017 at 20:33 UTC
    This falls into the general class of "I'm using a regex, but my expression is starting to look like noise." The fastest solution in this case is use the x modifier since you don't have any whitespace in your expression:
    s/ \) ([^()]+) \( / ] $1 [ /xg;
    That's your original expression with extra whitespace.

    I personally don't see the value in reducing your character count by 2 by avoiding the backslashes in the first place, but this type of process is always susceptible to Leaning_toothpick_syndrome. If I'm doing something like this, with potential nesting and the like, I always build a tree using tokens. My experience has generally shown that in these scenarios the fast solution is never actually fast.


    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

Re: $1[ (or "Does an array @1 exist in Perl ? - Yes!")
by LanX (Saint) on Oct 10, 2017 at 22:54 UTC
    It's not easy to understand what your question is, that's why you get fuzzy answers.

    > I guess that perl tried to interpret $1[ as element of an array @1?

    yes

    @1=a..c; my $a="012210"; $a =~ s/(.)/$1[$1]/g; print $a;

    abccba

    > So I solved this problem in two ways, using ...

    Excellent you even solved it, so what is the question again? :)

    Your title $1[ is - sorry - really crap, please see How do I compose an effective node title? for inspiration.

    And your question is obscured in between lots of regex line noise, please see How do I post a question effectively?

    Now the gory details ...

    you said in one of your replies

    > which looks to me as a bug.

    nope, but IMHO it's ...

    ... flawed by concept:

    Normally an identifier in Perl has to match something like /[_a-zA-Z^][_a-zA-Z0-9]*/ but special variables like $\ or $1 are exceptions (see perlvar#SPECIAL-VARIABLES for a list)

    They are global symbols and don't need to be declared.

    Unfortunately this covers other possible slots of such a symbol, like %hash, @array, $scalar, &code, *glob and probably also filehandle and format....

    (see perlmod#Symbol-Tables and perlref#Making-References point 7 for details)

    For instance %\ doesn't have any meaning, but since $\ is a special variable, it is

    • legally parsed and
    • globally available.

    I'd rather prefer that undefined special vars fail under strict, alas, we are talking about a language which supported this concept already in Perl4, i.e. long before it introduced lexicals and strict.

    Not a bug

    Since this /$array[/ is a parsing error and since 1 is not less a symbol than array it's not a bug.

    This is normally not a problem, but regex' tend to become messy.

    Cheers Rolf
    (addicted to the Perl Programming Language and ☆☆☆☆ :)
    Je suis Charlie!

      Then documentation should say that, not only scalar variables with names '\', '1' are valid, but also these names are valid for all structures. Otherwise it is a bug.

      One can use "$1[$2]$3[$4]$5" expecting no array (with impossible names according doc) interpretation.

      Thank you for informative reply and expanding name of a node to better!

        The fact that $1 is a pre-declared variable, and that @1 is not does not mean that @1 could not have been a variable, and consequently, that $1[... should not be seen as the beginning of an indexing into the @1 array. It really probably ought to be a strict violation first, since @1 isn't special, but is an identifier, and subject to the rules of parsing that apply to sigil-preceded identifiers when interpolated into a regexp quote-like construct.

        perl -E 'our @array = (1,2,3); *1=\@array; say for @1;' 1 2 3

        Here we cheated a little, using the typeglob syntax to create an array by the name of @1. Well, really a symbol for an array named @1, which happens to be an alias to @array in the symbol table. And it is shown to work. With that in mind, there's no reason that m/something$1[.../ should not be seen as the beginning of the indexing into an array element for interpolation within a regexp. Disambiguation can be achieved by wrapping the symbol portion of $1 in curly braces, as in ${1}:

        # $1 will be undef, so not relevant to the pattern. [0] will be a sing +le-character character class, so matches "0". perl -E 'our @array = (1,2,3); *1=\@array; say for @1; say "yes" if "0 +" =~ m/.?${1}[0]/;' 1 2 3 yes

        Otherwise, this will be variable interpolation:

        # $1[0] is seen as interpolation, placing the value of "1" into the re +gexp, which matches with the "1" in our target string. perl -E 'our @array = (1,2,3); *1=\@array; say for @1; say "yes" if "1 +" =~ m/.?$1[0]/;' 1 2 3 yes

        The unfortunate part here is that strict appears to be special cased for the numeric-variable symbols rather than specifically for scalars.


        Dave

        One can use "$1[$2]$3[$4]$5" expecting no array (with impossible names according doc) interpretation.

        No, the documentation does not say they are impossible at all:

        Perl variable names may also be a sequence of digits, a single punctuation character, or the two-character sequence: ^ (caret or CIRCUMFLEX ACCENT) followed by any one of the characters [][A-Z^_?\] . These names are all reserved for special uses by Perl; for example, the all-digits names are used to hold data captured by backreferences after a regular expression match.

        So @1, @2, @1066, etc. are all perfectly valid. They are just reserved for special uses by Perl.

        > Then documentation should say that, not only scalar variables with names '\', '1' are valid, but also these names are valid for all structures.

        I agree.

        > Otherwise it is a bug.

        It's a feature! ;]

        Honestly there are many issues with these "open source" docs, and I don't know how to solve them.

        The usual response is "contribute", but the result of more authors is just more confusion.

        We are somehow at the limit of the possibilities of self managed groups. (This observation doesn't only apply for the docs)

        regarding special symbols
        though in this particular case I'd suggest adding a remark to the beginning of perlvar and/or a caveat section at the end, to limit the amount of confusion.

        Cheers Rolf
        (addicted to the Perl Programming Language and ☆☆☆☆ :)
        Je suis Charlie!

Re: $1[
by holli (Abbot) on Oct 10, 2017 at 19:48 UTC
    You are using a screwdriver to stab someone. While that is also deadly, the right tool makes a much cleaner cut:
    $_ =~ tr/()/[]/;


    holli

    You can lead your users to water, but alas, you cannot drown them.
      Problem I was solving was more complicated, I only left some context in which I have used square brackets. I've simplified for show a problem of interpreting '$1[', which looks to me as a bug.

        No, for sure it is not a bug. When in doubt use the ${name} form inside of double quoted strings, or other contexts with similar rules. This could have happened with a var named $foo

        demerphq (dmq but i can't be bothered to log in)

Re: $1[
by thanos1983 (Parson) on Oct 11, 2017 at 08:58 UTC

    Hello rsFalse,

    Well I am having some questions based on your code.

    The sample of code that you provide us it gives me a different error (sample below):

    #!/usr/bin/perl use warnings; use strict; $\ = $/; $_ = reverse "(a+b)*c"; # or some longer sequence s/\)([^()]+)\(/]$1[/g; print scalar reverse y/][/)(/r; __END__ $ perl test.pl Missing right curly or square bracket at test.pl line 10, within strin +g syntax error at test.pl line 10, at EOF Execution of test.pl aborted due to compilation errors.

    Based on fellow Monk holli solution:

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; my $reversed = reverse "(a+b)*c"; # or some longer sequence $reversed =~ tr/()/[]/; my $str = reverse $reversed; say $str; __END__ $ perl test.pl [a+b]*c

    Question: why you reverse the string? Am I missing something here? (Sample below):

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; my $test = "(a+b)*c"; $test =~ tr/()/[]/; say $test; __END__ $ perl test.pl [a+b]*c

    An alternative way of resolving your issue (not more efficient - just for fun :D):

    #!/usr/bin/perl use strict; use warnings; use feature 'say'; sub replaceChar { my ($str, $char, $replace) = @_; substr($str, index($str, $char), length($char), $replace); return $str; } my $s = "(a+b)*c"; my $leftParenthesis = "("; my $rightParenthesis = ")"; my $leftCurlyBracket = "["; my $rightCurlyBracket = "]"; my $str = replaceChar($s, $leftParenthesis, $leftCurlyBracket); say $str; say replaceChar($str, $rightParenthesis, $rightCurlyBracket); __END__ $ perl test.pl [a+b)*c [a+b]*c

    BR / Thanos

    Seeking for Perl wisdom...on the process of learning...not there...yet!
Re: $1[
by demerphq (Chancellor) on Feb 06, 2019 at 12:28 UTC

    Both of these are reasonable solutions to the problem at hand.

    IMO there is a lot of discussion about red-herrings in this thread. That it happens inside of a s/// is a red-herring, the RHS of a s/// is essentially the same as a dq string, at least when not using the /e modifier. That this happens with $1 is a red-herring, it would happen with any named scalar followed by a square bracket in a double quoted string. That this happens with a square bracket is also a red-herring, it would also happen with any suffix which changed the name of the var sufficient to make perl think you were referring to another variable. This is why perl supports the bracketed version in the first place, to make it absolutely clear what variable is being interpolated and not be victim to stray concatenation that might change its name.

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://1201114]
Approved by holli
Front-paged by LanX
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others romping around the Monastery: (4)
As of 2024-04-19 13:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found