CGI和Perl脚本一个文件,传递参数

时间:2014-12-10 16:02:47

标签: perl cgi

我有一个脚本,它使用命令行参数(登记号)从NCBI网站获取摘要文件。

示例:

./efetch.pl NM_000040

现在我正在尝试使用HTML网页获取同一个文件,该网页通过CGI脚本获取表单请求。

我的问题:是否可以将CGI和我的Perl脚本合并到一个文件中,并在单次运行中将HTML表单参数从代码的CGI部分传递给perl脚本?

我试过做一些脚本但似乎CGI中的参数没有传递给Perl脚本。

非常感谢任何帮助。

CGI和Perl Script在一个文件中:

#!/usr/bin/perl -wT
use strict;
use warnings;
use LWP::Simple;
use CGI::Carp qw(warningsToBrowser fatalsToBrowser);

################### Environmental Variables ###################
my ($buffer, @pairs, $pair, $name, $value, %FORM);
# Read in text
$ENV{'REQUEST_METHOD'} =~ tr/a-z/A-Z/;
if ($ENV{'REQUEST_METHOD'} eq "POST")
{
read(STDIN, $buffer, $ENV{'CONTENT_LENGTH'});
} else {
$buffer = $ENV{'QUERY_STRING'};
}
#print "$buffer\n";
# Split information into name/value pairs
@pairs = split(/&/, $buffer);
foreach $pair (@pairs) {
($name, $value) = split(/=/, $pair);
$value =~ tr/+/ /;
#$value =~ s/%(..)/pack("C", hex($1))/eg;
$FORM{$name} = $value;
}
my $access    = $FORM{accession};
if ($access =~ m{\A(\w+\d+)\z}) {
$access = $1;
}

print "Content-type:text/html\r\n\r\n";
print "<html>";
print "<head>";
print "<title> CGI Program</title>";
print "</head>";
print "<body>";
if ($access eq "") {
    print "<h2> Please check the accession number</h2>";
exit;
}
print "<h2>$access</h2>";
print "</body>";
print "</html>";
print <HEADING
<html>
 <head>
  <title> Output result of the program </title>
 </head>
<body>
<h1> Summary result </h1>
 <table border=1>
  <tr>
   <th>S.No.</th>
   <th>Fragment</th>
   <th>Position</th>
   <th>Region</th>
   <th>GC%</th>
  </tr>
HEADING
;

######################## INPUT PARAMETERS #####################
my $utils = "http://www.ncbi.nlm.nih.gov/entrez/eutils";
my $db     = "nuccore";
my $query  = $access; #"$ARGV[0]" or die "Please provide input for the accession number. $!"; 

############### END OF INPUT PARAMETERS ######################
############### FILE DOWNLOAD FROM NCBI ######################
my $report = "gb";   # downloads the summary text file
open (IN,">", $query.".summary");

my $esearch = "$utils/esearch.fcgi?" . "db=$db&retmax=1&usehistory=y&term=";
my $esearch_result = get($esearch . $query);

$esearch_result =~ m|<Count>(\d+)</Count>.*<QueryKey>(\d+)</QueryKey>.*<WebEnv>(\S+)</WebEnv>|s;
my $Count    = $1; my $QueryKey = $2; my $WebEnv   = $3;
my $retstart; my $retmax=3;
for($retstart = 0; $retstart < $Count; $retstart += $retmax) {
my $efetch = "$utils/efetch.fcgi?" .
"rettype=$report&retmode=text&retstart=$retstart&retmax=$retmax&" .
"db=$db&query_key=$QueryKey&WebEnv=$WebEnv";
my $efetch_result = get($efetch);
print IN $efetch_result, "\n";
}
close (IN);

perl脚本中的print命令打印$access,但无法将$access的值传递给$query

HTML表单:

<form action="/cgi-bin/efetch.cgi" method="post" id="myform">
<div>
    NCBI accession number:<label for="accession"> <input type="text" name="accession">       </label><br>
    <input type="submit" value="Submit" form="myform">
 </div>
</form>

2 个答案:

答案 0 :(得分:0)

你的脚本比它需要的复杂得多。具体来说 - 您正在使用CGI模块(已弃用,因此您可能需要考虑其他内容*),但之后您将尝试在脚本中滚动自己的输入处理。

您可以编写一个发送&#39; POST&#39;或者&#39; GET&#39;数据自身进行处理。这根本不太难。

一个简单的例子可能是

#!/usr/bin/perl
use strict;
use warnings;
use Data::Dumper;

print "Content-Type: text/html\n\n";

my %param;
while ( <STDIN> ) {
   my ( $key, $value ) = split ( "=" );
   $param{$key} = $value;
}

print Dumper \%param;

print "<FORM METHOD=\"POST\">\n";
print "  <INPUT TYPE=\"text\" NAME=\"access\">\n";
print "  <INPUT TYPE=\"submit\">\n";
print "</FORM>\n";

这不是好的示例,但它可以正常工作,并希望它可以让您了解正在发生的事情 - {{1 {stuff}来自POSTSTDIN内容包含在网址中。

您可以测试此类输入的存在,并呈现基本表单或处理您获得的输入。

GET

有许多模块可以让这更容易(你甚至已经以CGI的形式使用了一个),所以我不建议这样做,对于真实的&#39; ; - 这纯粹是基础知识的例证。

使用 if ( $param{'access'} ) { #process it; else { #print form; } 模块,这可能是需要最少代码更改的事情,您可以使用&#39; CGI :: param()&#39;检索参数的方法:

CGI

但更完整的一个是考虑更深入的重写,并考虑使用一个更新的网络处理&#39;构架。确实有很多潜在的陷阱。 (虽然它确实取决于你对环境的控制程度 - 内部/有限的用户脚本,我比面对互联网更放松)。

*请参阅:CGI::Alternatives

答案 1 :(得分:0)

在2014年写一个CGI程序就像使用打字机一样。当然,它会起作用,但人们会非常奇怪地看着你。

但鉴于你已经有了一个CGI程序,让我们来看看如果你使用过去一千年没有过时的技术可能会是什么样子。

您的代码基本上存在两个潜在问题。

  1. 使用来自用户输入的名称打开文件。这违反了污点模式规则,因此你的程序就会死掉。如果你看过那里,你会在你的网络服务器错误日志中看到这个。
  2. 您实际上不需要将数据写入文件,因为您希望将数据发送到用户的Web浏览器。
  3. 所以这是代码的改进版本。它解决了我上面提到的两个问题,但它也使用了现代工具。

    1. CGI模块有一个param()方法,这使我们更容易将参数传递给我们的程序。我们还使用其header()方法输出CGI标头(基本上只是Content-type标头)。
    2. 我们使用模板模块将所有HTML移出代码并将其放在单独的区域中。在这里,我略微作弊,并把它放在CGI程序的DATA部分。通常我们会把它放在一个完全独立的文件中。请注意,分离Perl和HTML如何使程序看起来更清晰,更易于维护。
    3. 我不清楚你想要如何格式化你从其他网站获得的数据。所以我只是把它放在一个“预”标签中。你需要自己解决这个问题。

      以下是代码:

      #!/usr/bin/perl -T
      use strict;
      use warnings;
      use LWP::Simple;
      use Template;
      use CGI ':cgi';
      use CGI::Carp qw(warningsToBrowser fatalsToBrowser);
      
      my $access = param('accession');
      
      my $utils = "http://www.ncbi.nlm.nih.gov/entrez/eutils";
      my $db     = "nuccore";
      my $query  = $access;
      my $report = "gb";   # downloads the summary text file
      my $esearch = "$utils/esearch.fcgi?" . "db=$db&retmax=1&usehistory=y&term=";
      my $esearch_result = get($esearch . $query);
      
      my $data = '';
      if (my ($Count, $QueryKey, $WebEnv) = $esearch_result =~ m|<Count>(\d+)</Count>.*<QueryKey>(\d+)</QueryKey>.*<WebEnv>(\S+)</WebEnv>|s) {
        my $retstart;
        my $retmax=3;
        for ($retstart = 0; $retstart < $Count; $retstart += $retmax) {
          my $efetch = "$utils/efetch.fcgi?" .
            "rettype=$report&retmode=text&retstart=$retstart&retmax=$retmax&" .
            "db=$db&query_key=$QueryKey&WebEnv=$WebEnv";
          my $efetch_result = get($efetch);
          $data .= $efetch_result;
        }
      }
      
      my $tt = Template->new;
      print header;
      $tt->process(\*DATA, { data => $data })
        or die $tt->error;
      
      __END__
      <html>
        <head>
          <title> CGI Program</title>
        </head>
        <body>
          <h1>Input</h1>
          <form action="/cgi-bin/efetch.cgi" method="post" id="myform">
            <div>NCBI accession number:<label for="accession"> <input type="text" name="accession"></label><br>
              <input type="submit" value="Submit" form="myform"></div>
          </form>
      [% IF data -%]
          <h1>Summary Result</h1>
          <pre>
      [% data %]
          </pre>
      [% END -%]
        </body>
      </html>
      
相关问题