web-dev-qa-db-fra.com

Comment diviser une chaîne avec plusieurs modèles en perl?

Je veux diviser une chaîne avec plusieurs modèles:

ex.

my $string= "10:10:10, 12/1/2011";

my @string = split(/firstpattern/secondpattern/thirdpattern/, $string);

foreach(@string) {
    print "$_\n";
}

Je veux avoir une sortie de:

10
10
10
12
 1
2011

Quelle est la bonne façon de procéder?

14
quinekxi

Utilisez un classe de caractères dans le délimiteur d'expression régulière pour faire correspondre un ensemble de délimiteurs possibles.

my $string= "10:10:10, 12/1/2011";
my @string = split /[:,\s\/]+/, $string;

foreach(@string) {
    print "$_\n";
}

Explication

  • La paire de barres obliques /.../ indique l'expression régulière ou le modèle à mettre en correspondance.

  • La paire de crochets [...] désigne la classe de caractères de l'expression régulière.

  • À l'intérieur se trouve l'ensemble des caractères possibles qui peuvent être mis en correspondance: deux points :, virgules ,, tout type de caractère d'espace \s et barres obliques \/ (avec la barre oblique inverse comme caractère d'échappement).

  • Le + est nécessaire pour faire correspondre un ou plusieurs caractères précédant immédiatement celui-ci, qui est la classe de caractères entière dans ce cas. Sans cela, l'espace virgule serait considéré comme 2 délimiteurs séparés, vous donnant une chaîne vide supplémentaire dans le résultat.

32
stevenl

Mauvais outil!

my $string = "10:10:10, 12/1/2011";
my @fields = $string =~ /([0-9]+)/g;
5
ikegami

Vous pouvez diviser sur des non-chiffres;

#!/usr/bin/Perl
use strict;
use warnings;
use 5.014;

my $string= "10:10:10, 12/1/2011";
say for split /\D+/, $string;
3
Chris Charley

Si les nombres sont ce que vous voulez, extrayez les nombres:

my @numbers = $string =~ /\d+/g;
say for @numbers;

La capture des parenthèses n'est pas requise, comme spécifié dans perlop :

Le modificateur/g spécifie la correspondance de modèle globale, c'est-à-dire la correspondance autant de fois que possible dans la chaîne. Son comportement dépend du contexte. Dans un contexte de liste, il renvoie une liste des sous-chaînes auxquelles correspondent toutes les parenthèses de capture dans l'expression régulière. S'il n'y a pas de parenthèses, il renvoie une liste de toutes les chaînes correspondantes, comme s'il y avait des parenthèses autour du motif entier.

2
TLP
my $string= "10:10:10, 12/1/2011";

my @string = split(m[(?:firstpattern|secondpattern|thirdpattern)+], $string);

my @string = split(m[(?:/| |,|:)+], $string);

print join "\n", @string;
2
Trizen

Pour répondre à votre question initiale: vous cherchiez le | opérateur :

my $string = "10:10:10, 12/1/2011";

my @string = split(/:|,\s*|\//, $string);

foreach(@string) {
    print "$_\n";
}

Mais, comme le soulignent les autres réponses, vous pouvez souvent l'améliorer avec des simplifications ou des généralisations supplémentaires.

2
reinierpost

Comme vous analysez quelque chose qui est plutôt une date/heure, je me demande s'il serait plus judicieux d'utiliser DateTime :: Format :: Strptime pour l'analyser en un objet DateTime.

1
Dave Cross