2010-09-14 7 views
6

Je l'habitude d'utiliser des citations simples, mais parfois je reçois des lignes très longues que je ne peux pas casser et ont besoin aussi d'utiliser des caractères d'échappement, si je reçois quelque chose comme ceci:Comment puis-je citer une longue chaîne en Perl?

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

Je sais qu'il ya d'autres façons pour représenter les chaînes en Perl. Que recommanderais-tu?

MISE À JOUR Merci à tous pour vos suggestions SQL. J'apprends des choses précieuses, mais, ma question demeure (en général, indépendamment de SQL): y a-t-il un opérateur qui permet de citer sans attraper les sauts de ligne?

ce que je fais est quelque chose comme maintenant:

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

qui est assez laid.

+0

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

+0

* tousse * vulnérabilité d'injection * tousse * http://xkcd.com/327/ – Ether

Répondre

3

Non. Toutes les méthodes de création de chaînes de Perl 5 connaissent et incluent les nouvelles lignes. Vous pouvez utiliser l'opérateur de concaténation que vous avez fait dans votre question ou abstraire le code nécessaire pour résoudre le problème:

#!/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

Dans ce cas particulier, je vous recommande d'utiliser des espaces réservés, sauf si vous êtes absolument sûr à 100% que query_id de $ ne peut jamais contenir « drôles de personnages »

Obligatory xkcd reference

+0

voudriez-vous donner des détails sur les espaces réservés? –

+2

@David B Et même si vous pensez que vous êtes si sûr, allez-y et utilisez des espaces réservés de toute façon. Voir [Que sont les espaces réservés dans DBI, et pourquoi voudrais-je les utiliser?] (Http://www.perlmonks.org/?node_id=7548) –

+1

Elaboration sur http://bobby-tables.com/ – daxim

2

Dans l'exemple que vous avez donné, il n'y a aucune raison de ne pas casser la ligne et il n'est pas nécessaire d'échapper les guillemets simples.

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

Mais, comme d'autres l'ont souligné, pour les substitutions dans les requêtes SQL qui vont être transmis à vous dBi êtes beaucoup mieux à l'aide des espaces réservés.

+2

Vous devriez pas donner un exemple dangereusement incorrect. Montrez-lui la bonne façon de le faire avec des espaces réservés dès le départ, ou vous pouvez être sûr que quelqu'un va le copier/coller, voir que cela fonctionne et être satisfait. –

3

En tant que SQL vous citez alors envisager d'utiliser quelque chose comme SQL::Abstract pour créer votre requête.

Par exemple:

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

C'est ce que vous verriez dans $query:

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

et @bind:

xyzzy 

Alors $query a déjà été construit pour accepter SQL espace réservé et @bind h comme les valeurs nécessaires. Donc, son alors juste trucs habituels DBI comme celui-ci pour exécuter la requête:

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

Maintenant, vous avez toute la sécurité et optimisation des espaces réservés SQL fournissent (voir SQL injection Wikipedia entry)

Voir aussi cette précédente question SO: Is there SQL parameter binding for arrays?

/I3az/

10

J'aime ici les documents, bien que certains les méprisent parce que la terminaison doit apparaître au début de la ligne en dépit de votre niveau de retrait.J'aime aussi le formatage de mon SQL afin que je puisse facilement voir la structure dans l'instruction.

2

Pour la construction de texte général (re: votre mise à jour) une réponse exotique est d'utiliser un moteur de template. C'est un peu comme un printf sur les stéroïdes!

Voici un exemple en utilisant 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", 
}; 

Vous pouvez aussi construire comme ceci:

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

Et un exemple ici avec quelques citer, etc:

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

Un meilleur exemple est quelque chose comme ceci avec votre texte SQL original:

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

Voir aussi:


Et enfin aller de exotique à bizarre, vous pourriez même créer un nouvelle quote-like operator avec 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 merci draegtun! –

+0

Vous êtes les bienvenus.Et merci en retour de m'avoir inspiré d'écrire deux (ou est-ce trois!) Réponses! (surtout me faire souffler ma trompette PerlX :: QuoteOperator :) – draegtun

0

Bien qu'il n'y ait pas intégré dans l'opérateur pour ce faire, voici une autre approche qui pourrait fonctionner:

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

ou sous forme de deux étapes :

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

Les deux sont laids, mais fonctionnels.

Questions connexes