2008-12-08 13 views
9

Ich habe einen String, aus dem ich nur ein einziges Wort extrahieren wollen, aber mit einer numerischen daran angehängt, die in jeder Zeile unterschiedlich sein könnten:Wie kann ich einen Teilstring innerhalb einer Zeichenfolge mit Perl finden?

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

Ich möchte diese Datei analysieren und die die Werte erhalten von "stringXXX", von 0 bis 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; 

die obigen druckt die ganze Linie starten, möchte ich nur stringXXX

Antwort

13

Sie es erfassen müssen bekommen:

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

Erläuterung:

  • die Klammern capture was in 1 $ in ihnen ist. Wenn Sie mehr als einen Satz von Parens haben, wird der erste in $ 1, der zweite in $ 2 etc. aufgenommen. In diesem Fall haben $ 2 die tatsächliche Anzahl.
  • \ d {1,2} erfasst zwischen 1 und 3 Ziffern, so dass Sie zwischen 0 und 99 erfassen können. Mit den zusätzlichen 100 können Sie 100 explizit erfassen, da dies die einzige 3-stellige Zahl ist, die Sie abgleichen möchten.

bearbeiten: Die Reihenfolge der erfassten Zahlen wurde korrigiert.

+0

danke das hat geholfen :-) – gagneet

+0

wenn // -> während // g – jfs

+0

Danke @ J.F. Ich aktualisierte die Antwort –

-2

Ändern Sie einfach Drucken $ Muster zu drucken $ &, die bereits erfasst wird.

+0

Das Problem ist, dass das Capturen falsch gemacht wird. –

+0

Außerdem hat '$ &' schlechte Auswirkungen auf die Leistung Ihres gesamten Systems. Siehe http://search.cpan.org/perldoc?Devel::SawAmpersand – mpeters

+0

0. Ja, die Regex war falsch, aber mit $ & ist der kürzeste Code, um das richtige Ergebnis zu drucken. 1. Dies ist kein Bibliothekscode, die Auswirkung auf die Leistung ist die gleiche wie die Verwendung von $ 1. 2. Der globale PL_sawampersand Hack ist ein Perl-internes Implementierungsproblem und sollte in Perl behoben werden. – ididak

5

Abc.pl:

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

Beispiel:

$ 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 

Man beachte den Unterschied zwischen den Ausgängen. Was vorzuziehen ist, hängt von Ihren Bedürfnissen ab.

-1

Nicht überspezifizieren. Um den numerischen Teil zu erfassen, verwenden Sie einfach (\ d +). Dies wird eine beliebige Länge aufnehmen, so dass eines Tages, wenn die Affen, die Ihnen diese Datei zur Verfügung stellen, entscheiden, ihren Bereich auf 999 zu erweitern, Sie abgedeckt werden. Es ist auch weniger Gedanken, sowohl jetzt, wenn Sie schreiben, und später, wenn Sie beibehalten.

Seien Sie streng in was Sie emittieren, aber seien Sie liberal in was Sie akzeptieren.

+0

hängt es tatsächlich von der Spezifikation ab, die Sie erhalten. Wenn Sie ein Wegwerf-Skript schreiben, um nur diese Zahlen zu erfassen, wollen Sie nicht (\ d +) verwenden. –

+0

Ich kann es nicht herausfinden, Nathan ... warum nicht? Wenn ich nur ein Wegwerf-Skript schreibe, möchte ich keine zusätzliche Zeit investieren, um die Regex komplizierter zu machen. – skiphoppy