Verwenden von regulären Ausdrücken, um alles vor einem bestimmten Worttyp abzugleichen

Ich bin neu in regulären Ausdrücken.

Ist es möglich, alles vor einem Wort zu entsprechen, das ein bestimmtes Kriterium erfüllt:

z.B.

THIS IS A TEST - +++ Dies ist ein Test

Ich möchte, dass es ein Wort trifft, das mit einem Großbuchstaben beginnt und das nächste Zeichen Kleinbuchstaben ist. Das ist ein richtiges Wort. Ich möchte dann alles vor diesem Wort löschen.

Das obige Beispiel sollte produzieren: Dies ist ein Test

Ich möchte diese Verarbeitung nur so lange durchführen, bis sie das richtige Wort findet und dann anhält.

Jede Hilfe würde geschätzt werden.

Dank

Antwort auf "Verwenden von regulären Ausdrücken, um alles vor einem bestimmten Worttyp abzugleichen " 5 von antworten

Ersetzen Sie

^.*?(?=[A-Z][a-z])

durch die leere Zeichenfolge. Dies funktioniert für ASCII-Eingang. Für Nicht-ASCII-Eingaben (Unicode, andere Sprachen) gelten unterschiedliche Strategien.

Erklärung

.*?    Everything, until
(?=    followed by
[A-Z]  one of A .. Z and
[a-z]  one of a .. z
)

Die Java Unicode-fähige Variante wäre:

^.*?(?=\p{Lu}\p{Ll})

dann können Sie so etwas wie diese

'.*([A-Z][a-z].*)\s*'

.* matches anything
( [A-Z] #followed by an uper case char 
  [a-z] #followed by a lower case 
  .*)   #followed by anything
  \s*   #followed by zeror or more white space

tun Das ist, was Sie suchen, denke ich

Nachdem Sie ein wenig aufgewacht sind, müssen Sie nichts löschen oder sogar eine Untergruppe erstellen - finden Sie einfach das Muster, das an anderer Stelle in den Antworten ausgedrückt wird. Hier ist ein komplettes Beispiel:

import java.util.regex.*;

public class Test
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("[A-Z][a-z].*");

        String original = "THIS IS A TEST - - +++ This is a test";
        Matcher match = pattern.matcher(original);
        if (match.find())
        {
            System.out.println(match.group());
        }
        else
        {
            System.out.println("No match");
        }        
    }
}

EDIT: Originalantwort

Das sieht so aus, als ob es das Richtige tut:

import java.util.regex.*;

public class Test
{
    public static void main(String args[])
    {
        Pattern pattern = Pattern.compile("^.*?([A-Z][a-z].*)$");

        String original = "THIS IS A TEST - - +++ This is a test";
        String replaced = pattern.matcher(original).replaceAll("$1");

        System.out.println(replaced);
    }
}

Grundsätzlich ist es nicht, alles vor dem richtigen Wort zu ignorieren - es geht darum, alles vom richtigen Wort an zu gruppieren und den gesamten Text durch diese Gruppe zu ersetzen.

Das obige würde mit "*** FOO *** I am fond of peanuts" because the "I" wouldn't be considered a proper word. If you want to fix that, change the [a-z] to [a-z\s] which will allow for whitespace instead of a letter. scheitern, weil das "Ich" nicht als richtiges Wort angesehen würde. Wenn Sie dies beheben möchten, ändern Sie [a-z] in [a-z's], wodurch Leerzeichen anstelle eines Buchstabens zulässig sind.

([A-Z][a-z].+)

würde übereinstimmen:

Dies ist ein Text

Ich weiß, dass meine Meinung dazu wirklich nicht so populär ist, so dass ihr mich in Vergessenheit geraten könnt, wenn ihr wollt, aber ich muss ein wenig rant (und das enthält eine Lösung, nur nicht in der Art und Weise, wie das Plakat verlangt).

Ich verstehe wirklich nicht, warum Die Leute so schnell zu regulären Ausdrücken gehen.

Ich habe eine Menge String-Parsing (Verwendet, um Bildschirm-Scrape vt100 Menü-Bildschirme) und ich habe nie einen einzigen Fall gefunden, in dem reguläre Ausdrücke viel einfacher gewesen wäre, als nur Code zu schreiben. (Vielleicht wäre ein Paar ein wenig einfacher gewesen, aber nicht viel).

Ich verstehe, dass sie einfacher sein sollen, sobald man sie kennt - aber man sieht jemanden, der eine Frage wie diese stellt und merkt, dass es für jeden Programmierer nicht einfach ist, einfach zu sehen, indem er es anschaut. Wenn es kostet 1 Programmierer irgendwo in der Zeile 10 Minuten des Denkens, es hat einen riesigen Nettoverlust über nur Codierung, auch wenn Sie 5 Minuten brauchten, um 5 Zeilen zu schreiben.

Also wird es Dokumentation brauchen - und wenn jemand, der auf der gleichen Ebene ist, darauf stößt, wird er es nicht ohne Wissen außerhalb seiner Domain ändern können, auch nicht mit Dokumentation.

Ich meine, wenn das Plakat zu einem trivialen Fall fragen müsste - dann gibt es einfach nicht so etwas wie einen trivialen Fall.

public String getRealText(String scanMe) {
    for(int i=0 ; i < scanMe.length ; i++)
        if( isUpper(scanMe[i]) && isLower(scanMe[i+1]) )
            return scanMe.subString(i);
return null; }

Ich meine, es ist 5 Zeilen, aber es ist einfach, lesbar und schneller als die meisten (alle?) RE-Parser. Nachdem Sie einen regulären Ausdruck in eine Methode eingewickelt und kommentiert haben, ist der Größenunterschied nicht messbar. Der Zeitunterschied - nun ja, für das Poster wäre es offensichtlich eine LOT weniger Zeit gewesen -- wie es für den nächsten Kerl sein könnte, der über seinen Code kommt.

Und diese String-Operation ist eine von denen, die in C mit Zeigern noch einfacher sind - und es wäre noch schneller, da die Testfunktionen Makros in C sind.

Achten Sie übrigens darauf, dass Sie einen Platz im zweiten Slot suchen, nicht nur nach einer Kleinbuchstabenvariablen, sonst verpassen Sie alle Zeilen, die mit den Wörtern A oder I beginnen.