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

Greetings monks. I am having difficulties with the following code, in which I am trying to conditionally assign a variable based on matching the first character of a string contained in 2 other variables.
if ($B1=~ m/^*/ | $B2=~ m/^*/) { my $type; $type eq "S"; } else { $type eq "I"; }
Basically, I am searching two other variables, if either of them have "*" as the first character, then variable $type should be set to the character variable S, otherwise it should be set to I. The error message I am getting is: Global symbol "$type" requires explicit package name at /home/radon00/amr/sandbox/alpha/SNPtagger.pl line 48. Global symbol "$type" requires explicit package name at /home/radon00/amr/sandbox/alpha/SNPtagger.pl line 51. So I think the problem has to do with the fact that I am using the $type variable which is declared in the if block, and the $B1 and $B2 variables which were declared outside of the if block. I'm just not sure what the solution is. Here is the entire code just in case some context is needed:
my $SNP_FILE="SNP.test.out"; # Will be $out in future, just hardcoded +to SNP.report for testing now. open (LINES,"<$SNP_FILE") || die ("Could not open file! \n"); # Read S +NP File <LINES>; while ($SNP_FILE=<LINES>) { my ($contig, $PP, $UPP, $Cons, $Cov, $Conflicts, $B1, $B2)=split( +'\t', $SNP_FILE); #Split line of SNP File my $ratio=sprintf("%.2f",($Conflicts/$Cov)); #Creates new variabl +e of ratio of Conflict Count/Total Coverage $PP=$PP+1; # Bump padded position coordinate by 1, as gap4 coordi +nates are off by 1 base compared to bank file $Cons=~ s/-/*/; # Replace - with gap4 pad notation in consensus v +ariable $B1=~ s/-/*/; # Replace - with gap4 pad notation in Base 1 vari +able $B2=~ s/-/*/; # Replace - with gap4 pad notation in Base 2 vari +able chomp $B2; $contig=~ s/Contig/#/; # Replace contig with number sign so gap4 +can recognize contig identifier if ($B1=~ m/^"*"/ or $B2=~ m/^"*"/) { my $type eq "S"; } else { my $type eq "I"; } my $type; print "$contig $PP $Cons $Cov $Conflicts $B1 $B2 $ratio $type \n" +; } close (LINES);
Thanks for the help in advance!

Replies are listed 'Best First'.
Re: Setting Conditional Variable Based on Partial Match
by ikegami (Patriarch) on Dec 19, 2008 at 19:40 UTC

    I think the problem has to do with the fact that I am using the $type variable which is declared in the if block, and the $B1 and $B2 variables which were declared outside of the if block.

    Half-right. The problem is that $type is declared in the if block, but it's used outside of the block.

    my $type; if ($B1=~ /^\*/ || $B2=~ /^\*/) { $type = "S"; } else { $type = "I"; }

    or

    my $type = $B1 =~ /^\*/ || $B2 =~ /^\*/ ? "S" : "I";

    or

    my $type = grep(/^\*/, $B1, $B2) ? "S" : "I";
    • You're confusing eq (string comparison) for = (assignment). See perlop
    • | is for bit math. You want ||. See perlop
    • "*" is a special character in regexp patterns. You want "\*" to match that character. See perlre

    I didn't read any further. Hopefully, that will give you a good start.

Re: Setting Conditional Variable Based on Partial Match
by ccn (Vicar) on Dec 19, 2008 at 19:41 UTC

    First of all: use  use strict; and use warnings;. That will save a lot of time for you.

    It will be good to put backslash before * in regexp if you want to match an asterisk. (see perldoc perlre about metacharacters)

    Yes $type must be declared outside of condition block. But rather before if clause than after it. And seems you want to use = instead of eq when assigning a value to $type

    my $type = ($B1 =~ m/^\*/ or $B2 =~ m/^\*/) ? 'S' : 'I';
      Thanks for the response. I actually do use strict and warnings, I just left them out of the code that I pasted here. I'll include everything in my program in the future. The backslash tells perl to recognize the character "as is" and not as a special character, correct?
        > The backslash tells perl to recognize the character "as is" and not as a special character, correct?

        Yes with some exceptions:

            \t		tab             (HT, TAB)
            \n		newline         (NL)
            \r		return          (CR)
            \f		form feed       (FF)
            \b		backspace       (BS)
            \a		alarm (bell)    (BEL)
            \e		escape          (ESC)
            \033	octal char	(example: ESC)
            \x1b	hex char	(example: ESC)
            \x{263a}	wide hex char	(example: SMILEY)
            \c[		control char    (example: ESC)
            \N{name}	named Unicode character
        
        
            \l		lowercase next char
            \u		uppercase next char
            \L		lowercase till \E
            \U		uppercase till \E
            \E		end case modification
            \Q		quote non-word characters till \E
        

        see: perldoc perlop (Quote and Quote-like Operators)

Re: Setting Conditional Variable Based on Partial Match
by Lawliet (Curate) on Dec 19, 2008 at 19:41 UTC

    Are you trying to assign the value 'S' or 'I' to the variable $type? If so, use =, not eq. It is the assignment operator.

    Update (~2min after initial post): Ahh! Everyone just updated their replies! Mine looks pathetic now :P

    And you didn't even know bears could type.

      Yes, thats what I was trying to do. Thanks for the correction :) In SAS, which I know marginally better, you use "=" for numerical assigment and "eq" for character assignments so I thought perl might be the same.
Re: Setting Conditional Variable Based on Partial Match
by toolic (Bishop) on Dec 19, 2008 at 19:42 UTC
    Also, eq (perlop) is used for comparison, not for assignment. I think you want:
    $type = "S";

    Side note... this:

    $PP=$PP+1;

    can also be written more concisely as:

    $PP++;
Re: Setting Conditional Variable Based on Partial Match
by Anonymous Monk on Dec 20, 2008 at 09:59 UTC