2009-06-03 7 views
1

Ich muss eine Reihe von Statistiken aus Text analysieren, und sie sind alle als Zahlen formatiert.Regex, das alles vor einem bestimmten Zeichen entspricht?

Zum Beispiel dieser Absatz:

Insgesamt 81,8 Prozent von New York Stadt Schüler der Klassen 3 bis 8 sind erfüllt oder übertrifft Grade-Niveau Mathematik Standards, im Vergleich zu 88,9 Prozent der Studenten im Rest des Staates.

Ich möchte nur die 81 und 88 Zahlen, nicht die ".8" ​​und ".9", die folgen.

Wie kann ich das tun? Ich habe den Begriff Rückverweis oder Look-Ahead oder sowas gehört. Wird irgendwas davon helfen?

Ich benutze C#.

Edit: Es ist erforderlich, dass ich die "3" und die "8" im obigen Beispiel erhalten. Es ist nur ein einfaches Beispiel, aber ich brauche so ziemlich alle Zahlen.

+0

Die Zahlen hinter dem Komma sind statistisch signifikant über eine große Bevölkerung. Ich würde den Ausdruck "Prozent" verwenden, um die relativen Zahlen zu finden. – Craig

+0

Craig - Ich verstehe nicht, was du meinst - ich habe das nur als Beispiel benutzt - meine reellen Zahlen sind keine Prozentsätze. Ich muss nur die Zeichen entfernen, die nach dem "." und andere Muster, wie "e +". Dies war nur ein sehr einfaches Beispiel. –

Antwort

2

Wenn Sie wollen nicht mit Gruppen umgehen, können Sie einen Look-Ahead verwenden, wie Sie sagen; Dieses Muster findet alle Dezimalzahlen in der Zeichenfolge den ganzzahligen Teil:

Regex integers = new Regex(@"\d+(?=\.\d)"); 
MatchCollection matches = integers.Matches(str); 

matches enthält 81 und 88. Wenn Sie den ganzzahligen Teil jeder Zahlen übereinstimmen möchten (dezimal oder nicht), können Sie stattdessen für ganze Zahlen suchen, die mit einem nicht . starten:

Regex integers = new Regex(@"(?<!\.)\d+"); 

Dieses Mal passt 81 enthalten würde, 3 , 8 und 88.

+0

In Ihrer ersten Regex, sollten Sie '\ d +' vor dem endgültigen Schließen paren, so dass Sie nicht falsch positive Ergebnisse an den Enden der Sätze bekommen. –

+0

Ausgezeichneter Punkt. Ich ging mit '\ d', da es mir egal ist, wie viele es sind. Danke für die Korrektur. – ojrac

+0

In Ihrem zweiten Codeblock, welche Art von Syntax ist das? Ich weiß nicht was?

0
/(\d+)\.\d/g 

Dies wird eine beliebige Anzahl entsprechen, die eine Dezimalzahl es Folgendes (was meiner Meinung nach ist das, was Sie wollen), sondern nur die Zahlen vor dem Komma erfassen. \d erfasst nur Zahlen (gleich wie [0-9]), also macht es das ziemlich einfach.

Edit: Wenn Sie die drei und die acht auch wollen, müssen Sie nicht einmal auf die Dezimalzahl überprüfen.

Edit2: Sorry, behoben, so dass es alle Dezimalstellen ignorieren wird.

/(\d+)(?:\.\d+)?/g 
+0

Bitte sehen Sie meine Bearbeitung - Ich brauche alle Zahlen, aber streichen Sie die Zahlen nach dem Komma (meine tatsächlichen Daten hat verrückte Präzision) –

+0

Wenn ich Ihre zweite, bekomme ich die 9 und die 1, die ich nicht ' Ich will. –

3
/[^.](\d+)[^.]/ 

Wie unten nur angegeben verwenden MatchObj.Groups (1), um die Stelle zu bekommen.

+0

Will das nicht auch die Ziffern nach dem Komma greifen? Vielleicht möchte ich ein [^.] Davor setzen. –

1

Versuche:

[0-9]*(?=[3]) 

Es hat ein Look-Ahead verwendet nur Zahlen mit einem Komma gefolgt übereinstimmen.

C# Code:

Regex regex = new Regex("[0-9]+(?=[.])"); 
MatchCollection matches = regex.Matches(input); 
+1

Sie erhalten zu jedem Zeitpunkt einen leeren Eintrag, da Sie 0 oder mehr Ziffern anstelle von 1 oder mehr Ziffern eingeben. –

+0

Danke, war in Eile früher und war nicht wirklich aufgepasst – Stephan

0

Versuchen Sie es mit /(\d+)((\.\d+)?)/

Das bedeutet im Wesentlichen eine Folge von Ziffern entsprechen und einen optionalen Dezimalpunkt mit einer anderen Folge von Ziffern. Verwenden Sie dann MatchObj.Groups(1) für den ersten Übereinstimmungswert und ignorieren Sie den zweiten. nur

1
[^.](\d+) 

Von Ihrem Beispiel wird die „81“ entsprechen, „3“, „8“, „88“

Sie erhalten ein zusätzliches Zeichen erhalten, bevor Sie Ihre Nummer bekommen, aber Sie können schneiden Sie das in Ihrem Code aus.

0

Dies ist nicht in der Sprache, die Sie gefragt haben, aber es kann Ihnen helfen, über das Problem nachzudenken.

$ echo "A total of 81.8 percent of New York City students in grades 3 to 8 are meeting or exceeding grade-level math standards, compared to 88.9 percent of students in the rest of the State." \ 
| fmt -w 1 | sed -n -e '/^[0-9]/p' | sed -e 's,[^0-9].*,,' | fmt -w 72 
81 3 8 88 

Der erste Befehl fmt fordert die folgenden Befehle auf, jedes Wort einzeln zu betrachten. Der Befehl "sed -n" gibt nur diejenigen Wörter aus, die mit mindestens einer Zahl beginnen. Der zweite sed-Befehl entfernt das erste nicht-stellige Zeichen im Wort und alles danach. Der zweite Befehl fmt fasst alles in einer Zeile zusammen.

$ echo "This tests notation like 6.022e+23 and 10e100 and 1e+100." \ 
| fmt -w 1 | sed -n -e '/^[0-9]/p' | sed -e 's,[^0-9].*,,' | fmt -w 72 
6 10 1 
2

komplette C# Lösung:

/// <summary> 
/// Use of named backrefence 'roundedDigit' and word boundary '\b' for ease of 
/// understanding 
/// Adds the rounded percents to the roundedPercents list 
/// Will work for any percent value 
/// Will work for any number of percent values in the string 
/// Will also give those numbers that are not in percentage (decimal) format 
/// </summary> 
/// <returns>true if success, false otherwise</returns> 
public static bool TryGetRoundedPercents(string digitSequence, out List<string> roundedPercents) 
{ 
    roundedPercents = null; 
    string pattern = @"(?<roundedDigit>\b\d{1,3})(\.\d{1,2}){0,1}\b"; 

    if (Regex.IsMatch(digitSequence, pattern)) 
    { 
     roundedPercents = new List<string>(); 
     Regex r = new Regex(pattern, RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.ExplicitCapture); 

     for (Match m = r.Match(digitSequence); m.Success; m = m.NextMatch()) 
      roundedPercents.Add(m.Groups["roundedDigit"].Value); 

     return true; 
    } 
    else 
     return false; 
} 

Von Ihrem Beispiel werden 81, 3, 8 und 88