-1

I'm trying to access a series of webpages in perl and write them to a series of files. The code I have looks like this:

  open IN , "AbsoluteFinalData.txt"; #Each line has a number and ID name separated by a tab.

        while(my $line = <IN>){

    chop $line; #removes newline at the end
my @first_split = split(/\t/, $line);
my $IDnum = $first_split[0];
my $Uniprot = $first_split[1];

    system('Uniprot=$Uniprot; curl -o "$Uniprot.html" http://pfam.xfam.org/\protein/.$Uniprot'); #More stuff after

The program, however, is giving me fits when I try to call $Uniprot in system(). Is there any way to call a variable defined in the perl script using system()?

  • As an aside, you should get into the habit of using the three argument form of open with lexical filehandles. c/f http://stackoverflow.com/questions/1479741/why-is-three-argument-open-calls-with-autovivified-filehandles-a-perl-best-pract – Oesor May 28 '14 at 19:52

3 Answers3

3
system('Uniprot=$Uniprot; curl -o "$Uniprot.html" http://pfam.xfam.org/\protein/.$Uniprot');

You use single quotes, which doesn't interpolate. The literal command:

Uniprot=$Uniprot; curl -o "$Uniprot.html" http://pfam.xfam.org/\protein/.$Uniprot

Is being executed.

You want to interpolate your variables, which means using double quotes (and escaping contained ones:)

system("Uniprot=$Uniprot; curl -o \"$Uniprot.html\" http://pfam.xfam.org/\protein/.$Uniprot");

Or the qq quote-like operator which functions like the double quote but avoids needing to escape contained double quotes:

system(qq(Uniprot=$Uniprot; curl -o "$Uniprot.html" http://pfam.xfam.org/\protein/.$Uniprot"));
Oesor
  • 6,632
  • 2
  • 29
  • 56
  • given there's no shell interpretation or redirection involved, IMHO the OP would be far better using the "list" version of `system`. – Alnitak May 28 '14 at 19:50
3

Given that you're not relying on the system command to perform any shell interpretation or file I/O redirection, you can achieve everything you want safely like this:

system 'curl', '-o', "$Uniprot.html", "http://pfam.xfam.org/protein/.$Uniprot";

The "list" version of system is safer to use than the single string version because it prevents shell command injection attacks.

Note also the use of double quotes to enable Perl's own variable interpolation, and also that there's no need to create the shell local variable Uniprot=$Uniprot since it's not used by Curl and is only being used by you to attempt to perform variable interpolation yourself.

tjd
  • 4,064
  • 1
  • 24
  • 34
Alnitak
  • 334,560
  • 70
  • 407
  • 495
0

Perl only interpolates variables within double quotes ("..."), not single quotes ('...').

system("Uniprot=$Uniprot; curl -o \"$Uniprot.html\" http://pfam.xfam.org/\protein/.$Uniprot");

Will do the substitution you're looking for.

Paul Roub
  • 36,322
  • 27
  • 84
  • 93