【问题标题】:How can I quote a long string in Perl?如何在 Perl 中引用长字符串?
【发布时间】:2011-04-12 01:24:04
【问题描述】:

我通常使用简单的引号,但有时我会得到很长的行,我不能中断并且还需要使用转义字符,所以我得到这样的东西:

my $str = "select query_accession,query_tag,hit_accession,hit_tag,significance from summaryTables where query_id = \'$query_id\';"

我知道在 Perl 中表示字符串还有很多其他方法。你会推荐什么?

更新 感谢大家提供与 SQL 相关的建议。我学到了一些有价值的东西,但是,我的问题仍然存在(作为一般问题,不管 SQL 是什么):是否有一些运算符允许引用而不捕获换行符?

我现在做的是这样的:

my $str = "123 123 456 sdndfnd sdfdmd " .
 "dfsdjkfs 343489 dfjsdj 3 34kdfsk kd " .
 "fd kd9534 rfg 546 5";

这很丑。

【问题讨论】:

标签: perl string quotes


【解决方案1】:

没有。 Perl 5 的所有字符串创建方法都知道并包含换行符。您可以像在问题中那样使用连接运算符,也可以抽象出解决问题所需的代码:

#!/usr/bin/perl

use strict;
use warnings;

sub single_line {
    my @strings = @_;
    for (@strings) {
        s/\s+/ /g;
        s/^\s+|\s+$//g;
    }
    return wantarray ? @strings : $strings[0];
}


my $sql = single_line "
    select query_accession,query_tag,hit_accession,hit_tag,significance
    from summaryTables
    where query_id = ?;
";

print "[$sql]\n";

【讨论】:

    【解决方案2】:

    虽然没有内置运算符来执行此操作,但这里有另一种可行的方法:

    (my $str = qq(
    123 123 456 sdndfnd sdfdmd 
    dfsdjkfs 343489 dfjsdj 3 34kdfsk kd 
    fd kd9534 rfg 546 5
    )) =~ s/\n//g;
    

    或以两步形式:

    my $str = qq(
    123 123 456 sdndfnd sdfdmd 
    dfsdjkfs 343489 dfjsdj 3 34kdfsk kd 
    fd kd9534 rfg 546 5
    );
    $str =~ s/\n//g;
    

    两者都很丑,但很实用。

    【讨论】:

      【解决方案3】:

      对于一般的文本构建(re: your update),一个奇特的答案是使用模板引擎。它有点像类固醇上的printf

      这里是一个使用Template Toolkit的例子:

      sub buildtt {
          use Template;
          my $tt = Template->new( START_TAG => '{', END_TAG => '}' );
          $tt->process( \$_[0], $_[1], \my $output );
          return $output;
      }
      
      my $str = buildtt '{a} {b} {c}' => {
          a => "123 123 456 sdndfnd sdfdmd",
          b => "dfsdjkfs 343489 dfjsdj 3 34kdfsk kd",
          c => "fd kd9534 rfg 546 5",
      };
      

      你也可以这样构建:

      my $str2 = buildtt '{all.join(" ")}' => {
          all => [ "123 123 456 sdndfnd sdfdmd",
                   "dfsdjkfs 343489 dfjsdj 3 34kdfsk kd",
                   "fd kd9534 rfg 546 5" ],
      };
      

      这是一个带有一些引用等的示例:

      my $str3 = buildtt '{all.join(" ")}' => {
          all => [ "no quoted text here",
                   "here's some and here's some more",
                   q{$str2 was "buildtt"},
                   $str2 ],
      };
      

      一个更好的例子是你的原始 SQL 文本是这样的:

      my $sql = buildtt 'select {v.join(",")} from {t} where {q}' => { 
          v => [qw/ query_accession query_tag hit_accession hit_tag significance /],
          t   => 'summaryTables',
          q   => '( query_id = ? )',
      };
      

      另见:


      最后,你甚至可以用PerlX::QuoteOperator 创建一个新的quote-like operator

      use PerlX::QuoteOperator q_strip_newline => {
          -emulate => 'q',
          -with    => sub ($) {
              my $txt = shift;
              $txt =~ s/\n//g;
              $txt;
          },
      };
      
      my $str = q_strip_newline{123 123 456 sdndfnd sdfdmd
      dfsdjkfs 343489 dfjsdj 3 34kdfsk kd
      fd kd9534 rfg 546 5};
      

      /I3az/

      【讨论】:

      • 不客气。并感谢您激励我写两个(或者是三个!)答案! (尤其是让我吹我的 PerlX::QuoteOperator 小号:)
      【解决方案4】:

      作为您引用的 SQL,然后考虑使用 SQL::Abstract 之类的东西来构建您的查询。

      例如:

      use SQL::Abstract;
      
      my $sql = SQL::Abstract->new;
      my $query_id = 'xyzzy';  # arbitary value
      
      my ($query, @bind) = $sql->select( 
          'summaryTables',
          [qw/ query_accession query_tag hit_accession hit_tag significance /],
          { query_id => $query_id },
      );
      

      这就是您在$query 中看到的内容:

      SELECT query_accession, query_tag, hit_accession, hit_tag, significance FROM summaryTables WHERE ( query_id = ? )
      

      @bind:

      xyzzy
      

      所以$query 已经被构建为接受SQL 占位符并且@bind 具有必要的值。因此,它只是通常的DBI 这样的东西来运行查询:

      my $sth = $dbh->prepare( $query );
      $sth->execute( @bind );
      

      现在您拥有 SQL 占位符提供的所有安全性和优化功能(请参阅 SQL injection Wikipedia entry

      另请参阅之前的 SO 问题:Is there SQL parameter binding for arrays?

      /I3az/

      【讨论】:

        【解决方案5】:

        我喜欢这里的文档,尽管有些人鄙视它们,因为尽管您的缩进级别,终止符必须出现在行首。

        my $str = <<"SQL";
          SELECT 
            query_accession,
            query_tag,
            hit_accession,
            hit_tag,
            significance
          FROM   
            summaryTables
          WHERE 
            query_id = ?
        SQL
        

        我也喜欢格式化我的 SQL,这样我可以很容易地看到语句中的结构。

        【讨论】:

          【解决方案6】:

          查看perlop's Quote-Like Operators。使用qq 表示双引号,使用q 表示单引号。

          【讨论】:

            【解决方案7】:

            在你给出的例子中,没有理由不换行,也不需要转义单引号。

            my $str = "select query_accession,
                              query_tag,
                              hit_accession,
                              hit_tag,significance
                       from   summaryTables
                       where query_id = '$query_id';"
            

            但是,正如其他人所指出的,对于要传递给 DBI 的 SQL 查询中的替换,最好使用占位符。

            【讨论】:

            • 你不应该给出一个危险的错误例子。从一开始就向他展示使用占位符的正确方法,或者您可以确定有人会复制/粘贴它,看到它“有效”并感到满意。
            【解决方案8】:

            在这种特殊情况下,我建议使用占位符,除非您绝对 100% 确定 $query_id 永远不会包含“有趣的字符”

            Obligatory xkcd reference

            【讨论】:

            猜你喜欢
            • 2010-09-18
            • 2010-11-22
            • 1970-01-01
            • 1970-01-01
            • 2017-01-06
            • 1970-01-01
            • 2015-09-19
            • 2016-05-06
            • 1970-01-01
            相关资源
            最近更新 更多