http://www.perlmonks.org?node_id=557282

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

I have the following bit of code:

if ($i =~ m/[ -~]/) { $rhs .= $i; } else { $rhs .= "."; }

When I run it through a loop processing a string like "hello\nthere" it prints the following:

hello there

rather than

hello.there
as I would except.

I thought that the regex -~ would result in the range of ASCII characters from a space (ascii 32) through the tilde (ascii 126). A newline is ascii 10 so I thought I should get a "." for the newline.

Anyone have any thoughts on this?

Replies are listed 'Best First'.
Re: regex incorrectly matching newline
by ikegami (Patriarch) on Jun 23, 2006 at 18:38 UTC
    What's in $i? It should work fine (and does for me) when $i eq "\n".
    $rhs .= "hello"; $i = "\n"; if ($i =~ m/[ -~]/) { $rhs .= $i; } else { $rhs .= "."; } $rhs .= "world"; print("$rhs\n"); # Prints: hello.world

    You regexp reads as "contains a valid char". Maybe you need one of the following (equivalent to each other) regexps.
    $i !~ m/[^ -~]/     # Doesn't contain invalid chars
    $i =~ m/^[ -~]*\z/  # Only contains valid chars

      Well, after you asked the question I looked back at the code and found it actually looked like the follow (more code context included):

      $buf = "hello\nworld"; $l = length($buf); for ($x = 0; $x < $l; $x++) { $piece = substr($buf, $x, 1); $i = ord($piece); if ($i =~ m/[ -~]/) { $rhs .= $i; } else { $rhs .= "."; } }

      So, the error is actually mine and works fine when using the right variable, $piece, as:

      if ($piece =~ m/[ -~]/)

      Sorry for the wasted space to post this question.

        No problem. Of course, you could simplify your entire code down to:

        $buf = "hello\nworld"; $buf =~ s/[^ -~]/./g; $rhs .= $buf;

        The above alters the value of $buf in the process. Feel tree to make a copy of $buf and work with the copy if you want to preserve $buf's value.

Re: regex incorrectly matching newline
by rsriram (Hermit) on Jun 24, 2006 at 06:44 UTC

    Hi,

    I see a problem in your IF statement. Try this out:

    $i="hello\nworld";
    if ($i =~ s/[^ -~]/./g)
        {
        $rhs .= $i;
        }
        else
        {
        $rhs .= ".";
        }
    print $rhs;

    Sriram

Re: regex incorrectly matching newline
by GrandFather (Saint) on Jun 23, 2006 at 18:43 UTC

    Show us the loop. Your sample code matches if any character in $i is within the set. Unless you are iterating over the string one character at a time you are seeing expected behaviour.


    DWIM is Perl's answer to Gödel
Re: regex incorrectly matching newline
by ioannis (Abbot) on Jun 23, 2006 at 18:50 UTC
    The regex is not matching the "\n", it succeeds by matching the 'h' of "hello\nthere". Furthermore, even if you make the \n as the first character of $i, by setting $i = "\nthere", the regex will continue to succeed because it will matches the 't'.