Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot

Question of variable interpolation in regex

by SparkeyG (Curate)
on Nov 15, 2002 at 16:27 UTC ( #213188=perlquestion: print w/replies, xml ) Need Help??

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

I'm working on the regular Perl Quiz of the Week, and while I've got it solved, I don't understand why I had to do something to dwiw. The included code shows the pertinant problem.

I take a line of the box to be put into the output. $putNum is a boolean variable. The problem is that instead of updating $boxLine with the current word number, it continues to put in the number 1.

The problem went away if I instead use a seperate variable in the foreach line and then later assign its value to $boxLine.

Please help me understand why this is happening.

my $wordNum = 0; foreach my $boxLine ( @empty_square) { if ($putNum) { $wordNum ++; my $space = $boxLine =~ s/\./\./g; my $string = sprintf "%-*d", $space, $wordNum; $boxLine =~ s/\.+/$string/o; } else { $boxLine =~ s/\./ /g; } }

Replies are listed 'Best First'.
Re: Question of variable interpolation in regex
by tommyw (Hermit) on Nov 15, 2002 at 16:51 UTC

    This line $boxLine =~ s/\.+/$string/o; uses the /o modifier, so the regular expression is only compiled once. That is, even if the value of $string changes, the regular expression won't reflect that. So the first time through, it compiles as s/\.+/    1/o and never changes again.

    updated: Apparently, I'm talking rubbish. Sorry!

    Too stupid to live.
    Too stubborn to die.

      Actually, the left-hand side of the substitution (the regex) is the part that is only compiled once. The right-hand side will change as $string changes. Try this:
      my $foo = 'a'; for my $string ('b'..'z') { $foo =~ s/./$string/o; print "$foo\n"; }

      -- Mike


Re: Question of variable interpolation in regex
by SparkeyG (Curate) on Nov 15, 2002 at 16:56 UTC
    A few people commented that I wasn't clear in my question and also asked for example input and output. The input in this loop is:
    my @empty_square = qw(+----+ |....| |....| |....| +----+ );
    We iterate over several of these boxes, and need to replace . with spaces and a number in the upper left hand corner. I have some logic, that isn't included hear, to determine when to add the number.

    The desired output of this loop would be if $putNum is true, the replace |....| with |1   | the first time, |2   | the second, etc. However, all it does now, if $putNum is true, it replaces all |....| with |1   |.

    I can fix this if I replace the following:

    foreach my $boxLine ( @empty_square) {
    foreach my $line ( @empty_square) { my $boxLine = $line;
    I hope this makes it clearer. --Sparkey
      Ok I saw a couple of things..

      1) In your code you incremented your value even though the first line doesnt match "/\./". So you always start at 2 instead of 1.
      2) you were using sprintf for your output when perl already had what you wanted to do built in via the nifty 'x' operator...

      I also changed the var names, just cause I could :)
      So here is what I came up with
      #!/usr/local/bin/perl -wT use strict; my($putNum,$line,$s_count,$num,$n_line, @square); $putNum = 1; @square = ( '+----+', '|....|', '|....|', '|....|', '+----+' ); foreach $line (@square) { if (!$putNum) { $line =~ s/\./ /g; } else { if ($line =~ /\./) { $s_count = $line =~ s/\./\./g; $num++ if ($s_count); $n_line = "$num" . ' ' x ($s_count - length($num)); $line =~ s/\.+/$n_line/o; } } print "$line\n"; } # OUTPUT +----+ |1 | |2 | |3 | +----+
      Is this what you were looking for? The same number of spaces that were previously '.'s on the line?

      Happy Hackin :)

      /* And the Creator, against his better judgement, wrote man.c */
        I solved the 1st problem you rose when $putNum is decided. If the line being considered is either the top or bottom line, $putNum is false.

        As to your second point, tmtowtdi. ;-)

        But I see I still haven't been clear. :-(
        the output I'm seeing is

        +----+----+----+----+ |1 |1 |1 |1 | | | | | | | | | | | +----+----+----+----+
        When what I want is
        +----+----+----+----+ |1 |2 |3 |4 | | | | | | | | | | | +----+----+----+----+
        Take a look at my scratch pad for the full code
      Dunno, it works for me on perl 5.6.0, 5.6.1, and 5.8.0. Which version are you using?
      print join("\n", @empty_square), "\n"; +----+ |2 | |3 | |4 | +----+
Re: Question of variable interpolation in regex
by Thelonius (Priest) on Nov 15, 2002 at 22:40 UTC
    When what I want is +----+----+----+----+ |1 |2 |3 |4 | | | | | | | | | | | +----+----+----+----+
    Well, you'll need somthing like:
    while ($boxLine =~ s/(\.+)/sprintf("%-*d", length($1), $wordNum)/e) { $wordNum++ }
    But then you'll have to skip over the other lines which have blanks (you have multiple lines per square).

Log In?

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: perlquestion [id://213188]
Approved by AltBlue
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others studying the Monastery: (4)
As of 2022-09-27 07:56 GMT
Find Nodes?
    Voting Booth?
    I prefer my indexes to start at:

    Results (118 votes). Check out past polls.