2009-01-09 12 views
9

Quand je dis simple, je veux dire, à l'intérieur d'une expression, de sorte que je puisse le coller comme valeur dans un hachage sans le préparer d'abord. Je posterai ma solution mais je cherche un meilleur qui me rappelle moins de VB. :)Quel est le moyen le plus simple de renvoyer la première ligne d'une chaîne multiligne en Perl?

+0

Pourquoi l'aversion de le préparer à l'avance? Il faut habituellement un mojo sophistiqué pour travailler comme un seul doublure, ce qui est le contraire du simple. Bien qu'il soit amusant de comprendre ces choses, il est rarement une bonne idée de les utiliser dans un vrai programme, car l'amateur que vous obtenez, plus il est difficile de comprendre plus tard. –

+0

C'est une solution temporaire. :) Bon point cependant. – Kev

Répondre

23

Que diriez-vous

(split /\n/, $s)[0] 

?

Vous n'avez pas à vous soucier de ne pas être multiplate-forme car Perl is clever enough to take care of that.

+0

Merci, c'est ce que je cherchais! Je suis impatient de lire cet article aussi, car j'ai eu des problèmes avec les sauts de ligne dans le passé, mais peut-être que ce n'était pas la faute de Perl. – Kev

+0

Eh bien, Perl fait \ n signifier des choses différentes sur des systèmes différents, mais cela ne signifie pas que \ n est le séparateur d'enregistrement pour l'entrée. :) –

+0

Et, espérons juste que cette chaîne n'est pas énorme :) –

0
substr($s, 0, index($s, $/) > -1 ? index($s, $/) ||()) 
+0

LOL, oups ... merci! – Kev

4

Ce n'est pas aussi simple que vous le souhaitez, mais être simple, juste pour être court ne devrait pas toujours être l'objectif.

Vous pouvez ouvrir un descripteur de fichier sur une chaîne (comme une référence scalaire) et le traiter comme un fichier pour lire la première ligne:

 
my $string = "Fred\nWilma\Betty\n"; 
open my($fh), "<", \$string or die ...; # reading from the data in $string 
my $first_line = <$fh>; # gives "Fred" 
close $fh; 

Si tu voulais vraiment, je suppose que vous pourriez réduire à une expression:

$hash{$key} = do { open my($fh), "<", \$string; scalar <$fh> }; 

Quelle que soit la méthode que vous choisissez, vous pouvez toujours faire un sous-programme pour retourner la première ligne, puis utilisez l'appel de sous-programme dans votre tâche de hachage.

 
sub gimme_first_line { ... } 

$hash{$key } = gimme_first_line(\$string); 
+0

Sauf que cette chaîne multiligne n'est pas stockée dans un fichier ... – Kev

+0

Non, c'est une chaîne en mémoire. Vous pouvez le traiter comme un fichier si. –

+0

Oups, je n'ai pas lu votre code très attentivement. Je ne savais pas que tu pouvais faire ça! – Kev

2
($str =~ /\A(.*?)$/ms)[0]; 

Pour les grandes chaînes, ce sera plus rapide que

(split /\n/, $str)[0] 

comme suggéré par Manni. [Edit: supprimé la mention erronée de split /\n/, $str, 1.]

Si vous souhaitez inclure le terminal \n si elle est présente, ajouter \n? juste avant les paren de clôture du regex.

+0

Au lieu de votre première suggestion, pourquoi ne pas simplement '($ str = ~ /^(.*)/)[0]; '? –

+0

@JoshuaGreen: Vous pouvez même vous débarrasser du '^' dans votre solution. Quoi qu'il en soit, il est plus concis que le mien, mais plus difficile à comprendre car il repose sur le lecteur du code étant conscient que '.' ne correspond pas à un' \ n' en l'absence de '/ s'. Pour 5 autres caractères, mon code rend la sémantique difficile à mal comprendre. –

+0

Oui, j'ai réalisé ce matin que le '^' est superflu. Honnêtement, je n'étais pas capable de suivre une grande partie de ce que tu faisais sans tout regarder, mais c'était principalement dû à un manque de connaissance de ma part. Je n'aurais même pas pensé à utiliser une regex pour cette tâche. –