2010-09-14 4 views
6

Io di solito uso le virgolette semplici, ma a volte ho ottenere linee molto lunghe, che non riesco a rompere e anche bisogno di utilizzare caratteri di escape, in modo da ottenere qualcosa di simile:Come posso citare una lunga stringa in Perl?

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

So che ci sono vari altri modi per rappresentare le stringhe in Perl. Cosa raccomanderesti?

UPDATE Grazie a tutti per i suggerimenti relativi a SQL. Apprendo alcune cose preziose, ma la mia domanda rimane (come generale, indipendentemente da SQL): c'è qualche operatore che consente di quotare senza interferire con le interruzioni di riga?

quello che faccio ora è qualcosa di simile:

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

che è abbastanza brutto.

+0

vedere http://www.perlmonks.org/?node_id=401006 –

+0

* tosse * Vulnerabilità all'iniezione * tosse * http://xkcd.com/327/ – Ether

risposta

3

No. Tutti i metodi di creazione delle stringhe di Perl 5 conoscono e includono i newline. È possibile utilizzare l'operatore di concatenazione come avete fatto nella tua domanda, o astrarre il codice necessario per risolvere il problema:

#!/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"; 
1

In questo caso particolare mi consiglia di utilizzare segnaposto, a meno che non si è assolutamente sicuri al 100% che $ query_id non può mai contenere "personaggi divertenti"

Obligatory xkcd reference

+0

ti piacerebbe elaborare i segnaposto? –

+2

@David B E anche se pensi di essere sicuro, vai avanti e usa i segnaposto comunque. Vedi [Cosa sono i segnaposti in DBI e perché dovrei usarli?] (Http://www.perlmonks.org/?node_id=7548) –

+1

Elaborazione su http://bobby-tables.com/ – daxim

2

Nell'esempio che avete dato, non vi è alcun motivo per non interrompere la linea e non è necessario sfuggire alle virgolette singole.

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

Ma, come altri hanno fatto notare, per le sostituzioni in query SQL che stanno per essere passato a DBI si sta molto meglio utilizzare segnaposto.

+2

Si dovrebbe non dare un esempio pericolosamente scorretto. Mostragli il modo corretto di farlo con i segnaposti fin dall'inizio, o puoi essere sicuro che qualcuno lo copi/incolli, vedi che "funziona" e sii soddisfatto. –

3

Dato che il codice SQL che stai citando considera l'utilizzo di qualcosa come SQL::Abstract per creare la tua query.

Ad esempio:

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 }, 
); 

Questo è quello che si vede in $query:

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

e in @bind:

xyzzy 

Così $query è già stato costruito per accettare SQL segnaposto e @bind h come i valori necessari. Così la sua poi basta solita DBI cose come questa per eseguire la query:

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

Ora avete tutta la sicurezza e l'ottimizzazione che SQL segnaposto forniscono (vedi SQL injection Wikipedia entry)

Vedi anche domanda precedente SO: Is there SQL parameter binding for arrays?

/I3az/

10

mi piace qui i documenti, anche se alcune persone li disprezzano perché il terminatore deve apparire all'inizio della riga nonostante il tuo livello di rientro.

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

Mi piace anche formattare il mio SQL in modo da poter vedere facilmente la struttura nell'istruzione.

2

Per costruzione testo generale (Re: l'aggiornamento) una risposta esotica è quella di utilizzare un motore di template. È un po 'come un printf su steroidi!

Ecco un esempio di utilizzo 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", 
}; 

Si può anche costruire in questo modo:

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

Ed ecco un esempio con un po 'citando, ecc:

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

Un esempio migliore è qualcosa del genere con il testo SQL originale:

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 = ?)', 
}; 

vedi anche:


E infine va da esotico a strano potresti persino crearne uno nuova quote-like operator con 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/

+0

+1 grazie draegtun! –

+0

Sei il benvenuto.E grazie in cambio per avermi ispirato a scrivere due (o sono le tre!) Risposte! (soprattutto per farmi saltare la mia tromba PerlX :: QuoteOperator :) – draegtun

0

Mentre non c'è costruito in all'operatore di fare questo, ecco un altro approccio che potrebbe funzionare:

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

o in forma in due fasi :

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

Entrambi sono brutti, ma funzionali.