2008-12-08 10 views
9

J'ai une chaîne à partir de laquelle je veux extraire un seul mot, mais avec un numérique annexée, qui pourrait être différent dans chaque ligne:Comment puis-je trouver une sous-chaîne dans une chaîne en utilisant Perl?

This is string1 this is string 
This is string11 
This is string6 and it is in this line 

Je veux analyser ce fichier et obtenir les valeurs de "stringXXX", en partant de 0 à 100

# suppose ABC.txt contains the above lines 
FH1 = open "Abc.txt"; 
@abcFile = <FH1>; 

foreach $line(@abcFile) { 
    if ($pattern =~ s/string.(d{0}d{100}); 
     print $pattern; 

les impressions ci-dessus la ligne, je veux seulement obtenir stringXXX

Répondre

13

vous devez capturer:

while ($pattern =~/(string(100|\d{1,2}))/g) { 
    print $1; 
} 

Explication:

  • la capture entre parenthèses ce qui est en eux dans 1 $. Si vous avez plus d'un ensemble de parens, le 1er capture en $ 1, le second en $ 2 etc. Dans ce cas, $ 2 aura le nombre réel.
  • \ d {1,2} capture entre 1 et 3 chiffres, vous permettant de capturer entre 0 et 99. Le 100 supplémentaire vous permet de capturer 100 explicitement, car c'est le seul numéro à 3 chiffres que vous voulez faire correspondre.

edit: correction de l'ordre des nombres capturés.

+0

merci qui a aidé :-) – gagneet

+0

si // -> tandis que // g – jfs

+0

Merci @ J.F. J'ai mis à jour la réponse –

-2

Il suffit de changer le motif print $ pour imprimer $ &, qui est déjà capturé.

+0

Le problème est que la capture est mal faite. –

+0

En outre, '$ &' a de mauvaises implications sur les performances pour l'ensemble de votre système. Voir http://search.cpan.org/perldoc?Devel::SawAmpersand – mpeters

+0

0. Ouais, l'expression rationnelle était erronée mais en utilisant $ & est le code le plus court pour imprimer le bon résultat. 1. ce n'est pas le code de la bibliothèque, l'impact sur les performances est le même que l'utilisation de 1 $. 2. le hack PL_sawampersand global est un problème d'implémentation interne de perl et devrait être corrigé en perl. – ididak

5

Abc.pl:

#!/usr/bin/perl -w  
while(<>) { 
    while (/(string(\d{1,3}))/g) {  
    print "$1\n" if $2 <= 100; 
    } 
} 

Exemple:

$ cat Abc.txt 
This is string1 this is string 
This is string11 
This is string6 and it is in this line 
string1 asdfa string2 
string101 string3 string100 string1000 
string9999 string001 string0001 

$ perl Abc.pl Abc.txt 
string1 
string11 
string6 
string1 
string2 
string3 
string100 
string100 
string001 
string000 

$ perl -nE"say $1 while /(string(?:100|\d{1,2}(?!\d)))/g" Abc.txt 
string1 
string11 
string6 
string1 
string2 
string3 
string100 
string100 

Notez la différence entre les sorties. Ce qui est préférable dépend de vos besoins.

-1

Ne pas surspécifier. Pour capturer la partie numérique, utilisez simplement (\ d +). Cela permettra de capturer un nombre de n'importe quelle longueur, de sorte qu'un jour où les singes qui vous fournissent ce fichier décident d'étendre leur portée jusqu'à 999, vous serez couvert. C'est aussi moins pensé, à la fois maintenant quand vous écrivez, et plus tard quand vous maintenez. Sois strict dans ce que tu émets, mais sois libéral dans ce que tu acceptes.

+0

cela dépend en fait de la spécification qui vous est donnée. Si vous écrivez un script jetable pour capturer seulement ces nombres, vous ne voulez pas utiliser (\ d +) –

+0

Je ne peux pas comprendre, Nathan ... pourquoi pas? Si je suis en train d'écrire un script jetable, je ne veux pas investir plus de temps pour rendre l'expression rationnelle plus compliquée que cela. – skiphoppy

Questions connexes