Как я могу процитировать длинную строку в Perl? - PullRequest
6 голосов
/ 14 сентября 2010

Я обычно использую простые кавычки, но иногда я получаю очень длинные строки, которые я не могу разбить, и мне также нужно использовать escape-символы, поэтому я получаю что-то вроде этого:

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

Я знаю, что существуют различные другие способы представления строк в Perl. Чтобы вы посоветовали?

UPDATE Спасибо всем, ребята, за предложения, связанные с SQL. Я изучил некоторые ценные вещи, но мой вопрос остается (как правило, независимо от SQL): есть ли оператор, который позволяет заключать в кавычки без перерывов строки?

то, что я делаю сейчас, выглядит примерно так:

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

что довольно некрасиво.

Ответы [ 8 ]

10 голосов
/ 14 сентября 2010

Мне нравятся здесь документы, хотя некоторые люди презирают их, потому что терминатор должен появляться в начале строки, несмотря на ваш уровень отступа.

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

Мне также нравится форматировать мой SQL, чтобы я мог легко видетьструктура в заявлении.

5 голосов
/ 14 сентября 2010

Посмотрите в Операторы, похожие на цитаты perlop . Используйте qq для двойных кавычек и q для одинарных кавычек.

3 голосов
/ 14 сентября 2010

Нет.Все методы создания строк в 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";
3 голосов
/ 14 сентября 2010

В качестве 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-внедрениеЗапись в Википедии )

Также смотрите этот предыдущий вопрос SO: Есть ли привязка параметров SQL для массивов?

/ I3az /

2 голосов
/ 14 сентября 2010

Для создания общего текста ( re: ваше обновление ) экзотическим ответом является использование шаблонизатора.Это немного похоже на 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 :

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 /

2 голосов
/ 14 сентября 2010

В приведенном вами примере нет причин не прерывать строку и не нужно избегать одинарных кавычек.

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

Но, как отмечали другие, для подстановок в SQL-запросах, которые будут передаваться в DBI, гораздо лучше использовать заполнители.

1 голос
/ 14 сентября 2010

В этом конкретном случае я бы рекомендовал использовать заполнители, если вы не уверены на 100%, что $ query_id никогда не может содержать "забавные символы"

Обязательный xkcd ссылка

0 голосов
/ 15 сентября 2010

Хотя для этого не существует встроенного оператора, есть еще один подход, который может работать:

(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;

Оба безобразны, но функциональны.

...