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

Basically, different arrays have different pieces of information in them and I have to go from one to another to another from that. In this case, I have to go from each element in @Genes and extract its corresponding element from a long file which I read in as @lines. I keep getting a strange error that reads, syntax error at findscaffold.pl line 38, near "$N (" Does anyone know what this is? Here is the code. </p?

my @Genes = qw(A B C D) my @ptt = ("19384..003059 0 - - A","203581..39502 0 + - B) my @contig = (); my @Coordinates; my @Number; my $R; foreach my $G (@Genes){ for my $x (0..$#ptt){ if($ptt[$x] =~ /$G/){ push(@Coordinates,"$ptt[$x]"); print "$ptt[$x]\n";} } } foreach my $C (@Coordinates){ push (@Number, split(" ", $C));} my %hash = (); my $file = "scaffold_contig.txt"; open(IN, "<$file") or die "Cannot open file $file\n"; my @lines = <IN>; foreach $1 (@lines){ chomp($1); my %columns = split(">", $1);} close(IN); print "$lines[1];\n" foreach my $N (@Number){ for $R (0..$#lines){ if($lines[$R] =~ /$N/){ print "lines[$R]\n" } } }

Here is line 38: foreach my $N (@Number){

Replies are listed 'Best First'.
Re: Getting an unknown error
by QM (Parson) on Apr 23, 2015 at 14:10 UTC
    You're missing a semicolon terminating the print in the line before it. Update: I know this because it's my most frequent error.

    -QM
    --
    Quantum Mechanics: The dreams stuff is made of

Re: Getting an unknown error
by toolic (Bishop) on Apr 23, 2015 at 14:16 UTC
    Are you sure you posted your exact code? I get different compile errors. They begin with your first line because you need to use a semicolon at the end. The 2nd line is missing a double quote and a semi, etc.

    A good editor with syntax highlighting easily catches the quote typo.

    See also the Basic debugging checklist.

Re: Getting an unknown error
by Athanasius (Archbishop) on Apr 23, 2015 at 15:43 UTC

    Hello andybshaker,

    Others have answered your immediate question, but I want to comment on this part of your code:

    open(IN, "<$file") or die "Cannot open file $file\n"; my @lines = <IN>; foreach $1 (@lines){ chomp($1); my %columns = split(">", $1); } close(IN);

    (I have reformatted it a little to make it clearer.) First, the use of $1 as a loop variable is — well, unusual, to say the least. Normally, $1 contains the first matched string in the last regular expression match. In idiomatic Perl, the variable $_ is used implicitly:

    foreach (@lines){ chomp; my %columns = split(">"); }

    But second, and much more importantly, this foreach loop does literally nothing. You create a lexical variable %columns and fill it with split; then re-create it on the next iteration of the loop; and so on. And when the loop ends, the variable — having been declared within the scope of the loop — goes out of scope and is (eventually) garbage-collected. The contents of the file remain unchanged.

    And a final point: Please, please get into the habit of using a sane code formatting (indenting) style for nested loops. For example:

    foreach my $G (@Genes){ for my $x (0 .. $#ptt){ if ($ptt[$x] =~ /$G/){ push(@Coordinates,"$ptt[$x]"); print "$ptt[$x]\n"; } } }

    Why make your code harder to read than it needs to be? The maintenance programmer who comes to look at the code in six months time may well be you!

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

      ... use of $1 as a loop variable is ... unusual ...

      I was surprised that Perl is quite happy, both with and without full warnings and strictures, with aliasing $1, normally read-only, to a for-loop list, then chomp-ing it, but this is so under the few Perl versions I tried. I guess the alias does the trick.


      Give a man a fish:  <%-(-(-(-<

        "does the trick ... and could be considered a bug? Well, that, or an error in the docs. I think that p5p or others should consider this.

        Yes, if for no other reason than that many of us believe as did AnomalousMonk ... and in my case, at least, (sometimes-unreliable-) memory tells me I got my notion from some authoritative documentation.

        Quick 'n dirty search lead to this, in discussion of regex vars inside perlvars (which may or may not be where I got the idea that $1 is reserved for regexen... and read_only):
        $<digits> ($1, $2, ...)
        
        Contains the subpattern from the corresponding set of capturing parentheses from the last successful pattern match, not counting patterns matched in nested blocks that have been exited already.
        
        These variables are read-only and dynamically-scoped.
        
        Mnemonic: like \digits.

        From perlvar for 5.20.1, and likewise, in the docs for 5.18.4:

          These variables are read-only and dynamically-scoped.

        I suspect that statement can be found at least back to 5.10 and maybe to 5.8.

        Somewhere here, there's a big Ooops!

Re: Getting an unknown error
by ww (Archbishop) on Apr 23, 2015 at 14:46 UTC

    i see three double-quotes in your Ln 3 (as displayed here; your local Ln numbers seem to be different based on the final note in your OP):

    my @ptt = ("19384..003059 0 - - A","203581..39502 0 + - B)

    That alone would bork the entire script, unless you've made a copy-paste error or typo when posting here.

    If you're not already doing so, you'll find that adding use strict; use warnings; will be helpful. If you need even more info on problems with a script, the combination of use diagnostics; and perl -c scriptname.pl can be very helpful.

      Update: this post uses the observations of missing semi-colons and unmatched quotes in previous replies but is intended to criticize the original post Getting an unknown error when it employs the second person.

      It would seem evident that this script never ran, with the missing semi-colons and troubled declaration of @ptt. When you're struggling with syntax, start with what compiles and behaves well and make revisions as you near your goal. Download Perl::Tidy using cpan or apt-get to gussy it up before sharing it with the monastery.

      $ perltidy -b -i=2 gene3.pl

      To make this program work, there must be some type of data to read in. It doesn't take too much effort to seed it with some values for testing purposes:

      $ cat scaffold_contig.txt this>that 5>10 $

      I prefer to use the say feature, which one gets by use 5.010;. It obviates having to paste newlines on the ends of print statements and makes seeing the contents of an array a cinch:

      $ perl gene3.pl ptt is O P Q R S T U V W X Y Z line 0 is this>that line 1 is 5>10 lines are this>that 5>10 $ cat gene3.pl use strict; use warnings; use 5.010; my @Genes = qw(A B C D); my @ptt = ( 19384 .. 3059, "O" .. "A" ); #what is this supposed +to be? my @contig = (); my @Coordinates; my @Number; my $R; say "ptt is @ptt"; foreach my $G (@Genes) { for my $x ( 0 .. $#ptt ) { if ( $ptt[$x] =~ /$G/ ) { push( @Coordinates, "$ptt[$x]" ); print "$ptt[$x]\n"; } } } foreach my $C (@Coordinates) { push( @Number, split( " ", $C ) ); } my %hash = (); my $file = "scaffold_contig.txt"; open( IN, "<$file" ) or die "Cannot open file $file\n"; my @lines = <IN>; foreach (@lines) { chomp(); my %columns = split( ">", $_ ); # nothing happens with %columns and then the scope changes } close(IN); say "line 0 is $lines[0]"; say "line 1 is $lines[1]"; say "lines are @lines"; foreach my $N (@Number) { for $R ( 0 .. $#lines ) { if ( $lines[$R] =~ /$N/ ) { print "lines[$R]\n"; } } } $

      I'd be very interested to see what this looks like as code that performs to specification. Good luck.

Re: Getting an unknown error
by ikegami (Patriarch) on Apr 24, 2015 at 16:27 UTC
    $ perl -MDevel::Peek \ -e'$x="abc"; Dump($x); Dump($1); for $1 ($x) { Dump($1); }' SV = PV(0xd0e9e0) at 0xd2b810 REFCNT = 1 FLAGS = (POK,IsCOW,pPOK) PV = 0xd33f20 "abc"\0 CUR = 3 LEN = 10 COW_REFCNT = 1 SV = PVMG(0xd23870) at 0xd36138 REFCNT = 1 FLAGS = (GMG,SMG) IV = 0 NV = 0 PV = 0 MAGIC = 0xd44e10 MG_VIRTUAL = &PL_vtbl_sv MG_TYPE = PERL_MAGIC_sv(\0) MG_OBJ = 0xd36120 MG_LEN = 1 SV = PV(0xd0e9e0) at 0xd2b810 REFCNT = 2 FLAGS = (POK,IsCOW,pPOK) PV = 0xd33f20 "abc"\0 CUR = 3 LEN = 10 COW_REFCNT = 1

    Before the loop, the symbol $1 accesses the scalar at address 0xd36138.

    Inside the loop, the symbol $1 accesses the scalar at address 0xd2b810, which is the same scalar accessed by $x.

    The read-only property of $1 is a property of the scalar. At your own request, you are not accessing that scalar within the body of the loop.

    The capture fetching property of $1 is a property of the scalar. At your own request, you are not accessing that scalar within the body of the loop.

      Arguably, the lack of a warning is a bug here (at the very least).

      Note that the dynamic scoping of $1 appears to be a property of the scalar as well. Masking it over will break pretty much anything called from within that loop, but not only—signal handlers break too.

      $SIG{ALRM} = sub { "Yes" =~ /.*/; print "$&\n"; }; for $& ("No!") { alarm (1); sleep 2; }

        As far as I'm concerned, anything other than for my $var (LIST) and for $_ (LIST) should be avoided. But it's probably best if enforced by perlcritic rather than warnings.

        Honestly, it's rather obvious that $1 is special. If you start mucking with special vars, you get what you deserve.