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

Hi, Monks...

I'm trying to initialize a variable to the transliterated scalar value of another variable. I'm unable to make the following work:

#!/usr/bin/perl/ -w use strict; open UDATA, '<', "todo.users" or die "Failed to open userdata... $!"; while (my $line = <UDATA>) { chomp $line; my $nuline =~ tr/a-zA-Z/n-za-mN-ZA-M/; print "$nuline\n"; } close UDATA;

Why does this not print the transliterated value of $line?

Thanks!

Replies are listed 'Best First'.
Re: Problem using transliteration to modify a variable...
by FunkyMonk (Bishop) on Jul 04, 2007 at 19:31 UTC
    Your input is in $line and you're trying to transliterate $nuline without first assigning $line to $nuline. Compare your program with this:

    while (my $line = <DATA>) { chomp $line; (my $nuline = $line) =~ tr/a-zA-Z/n-za-mN-ZA-M/; print "$nuline\n"; } __DATA__ me you someone else

    Output:

    zr lbh fbzrbar ryfr

    update:: output added

Re: Problem using transliteration to modify a variable...
by blazar (Canon) on Jul 04, 2007 at 20:00 UTC
    chomp $line; my $nuline =~ tr/a-zA-Z/n-za-mN-ZA-M/;

    It doesn't work like that. That is, you're expecting:

    • tr to act on $line, this is the weakest point, since there's nothing connecting them;
    • the transliterated string to be put in $nuline, which also doesn't make since you don't have an assignment to it, and even if you had, then it would assign the return value of tr which is not the transliterated string;

    Instead you

    • assign to $line;
    • apply tr to a freshly created $nuline, which is also undefined. So that, BTW, if you were under warnings as you should, you would have get one.

    The solution is to

    my $nuline = $line; $nuline =~ tr/a-zA-Z/n-za-mN-ZA-M/;

    which can be shortened to

    (my $nuline = $line) =~ tr/a-zA-Z/n-za-mN-ZA-M/;
Re: Problem using transliteration to modify a variable...
by GrandFather (Saint) on Jul 04, 2007 at 20:55 UTC

    Either the code shown is not the code you ran, you ran it without strictures, or you ignored the warnings generated.

    Using strictures is laudable. Ignoring the results of using strictures is dumb. Not telling us that you received warnings when running your code is dumb too.

    The great big fat hints you should have seen and pondered were:

    Use of uninitialized value in transliteration (tr///) at noname.pl lin +e 9, <DATA> line 1. Use of uninitialized value in concatenation (.) or string at noname.pl + line 10, <DATA> line 1.

    Note that I used a __DATA__ (see the Special Literals sub-section) section rather than using an external file for the test code so the line numbers will differ somewhat from yours.


    DWIM is Perl's answer to Gödel
      GrandFather wrote:

      The great big fat hints you should have seen and pondered were: Use of uninitialized value in transliteration (tr///) at noname.pl lin +e 9, <DATA> line 1. Use of uninitialized value in concatenation (.) or string at noname.pl + line 10, <DATA> line 1. download Note that I used a __DATA__ (see the Special Literals sub-section) section rather than using an external file for the test code so the line numbers will differ somewhat from yours.

      I, in fact, do pay attention to output when I have strictures in play. My problem is with the interpretation of much of strictures output, which I sometimes find difficult. I'm sorry, however, to have neglected to post that output... I'll do better next time.

      With regard to the reference to using __DATA__ ...
      I followed up with reading the recommended Special Literals sub-section. It appears to be a very useful tool for script portability and testing. Thanks, for that bit of information!

      One question, though, regarding the use of __DATA__, when a script requires two or more sets of data. How would one, then, represent and call upon the subsequent sets?

      Thanks, again!

        It depends a lot on context. You can have only one __DATA__ section, but you could put section markers in it if appropriate (your code would need to recognize them though).

        Another technique for embedding blocks of input is to use here docs (see the <<EOF section in perlop):

        use warnings; #use strict; my $text1 = <<TEXT; This is the text for \$text1. Note that multiple lines are allowed. Note too that the terminating line must exactly match the string betwe +en the << and the ; on the starting line. In particular any white space must mat +ch exactly. TEXT print $text1;

        Prints:

        This is the text for $text1. Note that multiple lines are allowed. Note too that the terminating line must exactly match the string betwe +en the << and the ; on the starting line. In particular any white space must mat +ch exactly.

        Other tricks that may help for posting questions here are discussed in I know what I mean. Why don't you?.

        Update: fixed link


        DWIM is Perl's answer to Gödel
Re: Problem using transliteration to modify a variable...
by cgmd (Beadle) on Jul 04, 2007 at 20:39 UTC
    I understand it, now...

    Thanks!