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

Hello all, I'm seeing some confusing behavior with <STDIN> in my script (on Win 10 / Strawberry Perl), prompting for user input.

print "song: $string\n Correct? y/n: "; my $res = <STDIN>; chomp($res); if($res =~ /n/i){ print "Enter correct text: "; $str = <STDIN>; chomp $str; print "new: ", $str, $/; } print "str: ", $str, $/; my $newfile = "$str.mp3"; print "newfile: $newfile\n";

The output looks like this, if I enter 'ssss' as STDIN:

song: Fossil Aerosol Mining Project - Nu Message Correct? y/n: n Enter correct text: ssss new: sssss str: sssss .mp3ile: ssss

Note on the last line that ".mp3" jumps to the beginning of the line in the output (and variable value doesn't include it). That is, it should print "newfile: ssss.mp3". Any ideas what I'm doing wrong? Thanks as always.

Replies are listed 'Best First'.
Re: Strange behavior with STDIN
by kcott (Archbishop) on Oct 26, 2021 at 01:10 UTC

    G'day slugger415,

    The effect you're seeing with the four characters of ".mp3" overwriting the first four characters of "newfile", generally indicates an embedded carriage return. Such as:

    $ perl -e 'my $x = "newfile"; my $y = "\r.mp3"; print "$x$y\n"' .mp3ile

    You haven't shown your whole code, or cut it down to something that reproduces the behaviour (see SSCCE).

    I suspect you haven't used the strict and warnings pragmata: they're certainly not included with the code you posted.

    Your $str appears to be a package variable: action-at-a-distance is a possibility.

    Interspersing \n and $/ is questionable. Why are you doing this?

    — Ken

      Thank you for the helpful response. I was using strict but not warnings; adding the latter uncovered a couple of minor issues unrelated to this.

      Oddly what did work was adding two chops (not chomps).

      chop $str; chop $str;

      Odd because I've never run across this problem before.

      As to why I'm interspersing \n and $/, well let's just call it lazy typing, sometimes one seems easier than the other. :-)

      Thanks again.

        $str =~ s/\s+\z//; is a far better (and more portable) solution.

Re: Strange behavior with STDIN
by LanX (Saint) on Oct 26, 2021 at 00:57 UTC
    Newline differs between different OS, on Win it's 2 characters CR-LF

    Looks like your chomp only cut the line feed but not the carriage return out.

    Did you change the setting of $/? It should be "\n"?

    From chomp:

    > This safer version of chop removes any trailing string that corresponds to the current value of $/ (also known as $INPUT_RECORD_SEPARATOR

    Cheers Rolf
    (addicted to the Perl Programming Language :)
    Wikisyntax for the Monastery

      chomp only removes $/, which is a LF (by default). Even on Windows.

      That's not a problem because the CR are usually removed by the time you use chomp.

      On a Windows build,
      text input handles replace CR+LF with just LF.
      text output handles replace LF with CR+LF.

      Either the OP is reading Windows text on a unix build of perl, or STDIN has been binmoded.

      I suppose another possibility is that the input is garbage of the form "name␍␍␊" which is transformed into "name␍␊" on read and chomped to "name␍".

      Hi Rolf, I tried setting $/ = "\n;" and that didn't seem to help. But as mentioned elsewhere using two chop's did the trick. Weird but it works. Thanks for your help.

      Scott

        two chops is a very radical solution, because you might loose valid characters.

        I'd rather go with a regex like suggested by Ikegami.

        You should really try to figure out why your system is acting so strangely.

        Cheers Rolf
        (addicted to the Perl Programming Language :)
        Wikisyntax for the Monastery

Re: Strange behavior with STDIN
by slugger415 (Monk) on Oct 26, 2021 at 00:35 UTC

    it occurs to me this might have nothing to do with STDIN but how I'm assigning the .mp3 extension. Though I've tried various ways to do that too, including:

    my $newfile = $str . ".mp3";