Excel: Letzte Übereinstimmung von Zeichen und Zeichenfolge in einer Zeichenfolge

187

Gibt es eine effiziente Möglichkeit, die letzte Zeichen- / Zeichenfolgenübereinstimmung in einer Zeichenfolge mithilfe von Basisfunktionen zu identifizieren? Dh nicht das letzte Zeichen / string von der Saite, aber die Position eines Zeichens / letzte Vorkommen der Zeichenkette in einem String. Searchund findbeide arbeiten von links nach rechts, so dass ich mir nicht vorstellen kann, wie ich ohne langwierigen rekursiven Algorithmus anwenden soll. Und diese Lösung scheint jetzt veraltet zu sein.

Geotheorie
quelle
3
Weil ich die Position der letzten Instanz von zB Punkt "will". in der Zeichenfolge "one.two.three.four"
Geotheory
6
Amüsant, wie eine fehlerhafte Lektüre der Frage Stimmen
einbringt
1
Ich würde sagen, schauen Sie es aus der anderen Perspektive an, es bedeutet, dass andere Leute auch nicht verstanden haben, was Sie in Ihrer Frage gemeint haben, und so dachte, der Vorschlag sei die richtige Lösung ... Sogar Ihre ausgewählte Antwort begann mit "Ich denke, ich Verstehe, was du meinst "... Keine Kritik, sondern eine Aufforderung, deine Fragen verständlicher zu machen, damit die Leute leichter antworten können.
John Bustos
Ich habe das Beispiel auf die Frage hinzugefügt, aber ich denke , dass es genug war , dies über das letzte Zeichen eines Strings aus einer Abfrage zu unterscheiden: searchund findbeide Abfrage - String Inhalt , ‚Spiel‘ ist ein Standardbegriff sowie das verknüpfte Beispiel.
Geotheory
Mögliches Duplikat von Wie extrahiere ich den letzten Teilstring aus einer Excel-Spalte?
Jean-François Corbett

Antworten:

1

Mit neueren Versionen von Excel kommen neue Funktionen und damit neue Methoden. Obwohl es in älteren Versionen replizierbar ist (ich habe es noch nicht gesehen), kann man mit Excel O365 Folgendes verwenden:

=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),1)="Y"))

Dies kann auch verwendet werden, um die letzte Position von (überlappenden) Teilzeichenfolgen abzurufen:

=MATCH(2,1/(MID(A1,SEQUENCE(LEN(A1)),2)="YY"))

| Value  | Pattern | Formula                                        | Position |
|--------|---------|------------------------------------------------|----------|
| XYYZ   | Y       | =MATCH(2,1/(MID(A2,SEQUENCE(LEN(A2)),1)="Y"))  | 3        |
| XYYYZ  | YY      | =MATCH(2,1/(MID(A3,SEQUENCE(LEN(A3)),2)="YY")) | 3        |
| XYYYYZ | YY      | =MATCH(2,1/(MID(A4,SEQUENCE(LEN(A4)),2)="YY")) | 4        |

Während dies beides erlaubt, kein beliebiges Ersatzzeichen mehr zu verwenden und überlappende Muster zuzulassen, ist der "Nachteil" die Verwendung eines Arrays.


Hinweis: Sie können dasselbe Verhalten auch in älteren Excel-Versionen erzwingen

=MATCH(2,1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"))

Eingegeben durch CtrlShiftEnteroder Verwenden einer Inline INDEX, um implizite Schnittpunkte zu beseitigen:

=MATCH(2,INDEX(1/(MID(A2,ROW(A1:INDEX(A:A,LEN(A2))),1)="Y"),))
JvdV
quelle
1
Ich denke, dies erbt jetzt die Zecke, obwohl die volle historische Auszeichnung zu @ tigeravatars langjähriger Lösung stackoverflow.com/a/18617720/1156245
geotheory
Hinweis: Während mein Vorschlag beim skizzenhaften Code-Golf gewinnen würde, wird die Verwendung von Arrays nicht immer empfohlen, wenn sie in großen Mengen verwendet werden. Es hat jedoch andere Vorteile, die ich explizit zu erwähnen versucht habe. Dies macht die Antwort von @Tigeravatar genauso relevant wie zuvor!
JvdV
345

Ich glaube ich verstehe was du meinst. Angenommen, Sie möchten das am weitesten rechts stehende \ in der folgenden Zeichenfolge (die in Zelle A1 gespeichert ist):

Laufwerk: \ Folder \ SubFolder \ Filename.ext

Um die Position des letzten \ zu erhalten, würden Sie diese Formel verwenden:

=FIND("@",SUBSTITUTE(A1,"\","@",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))

Das sagt uns, dass das am weitesten rechts stehende \ bei Zeichen 24 ist. Dazu wird nach "@" gesucht und das allerletzte "\" durch ein "@" ersetzt. Es bestimmt den letzten mit

(len(string)-len(substitute(string, substring, "")))\len(substring)

In diesem Szenario ist der Teilstring einfach "\" mit einer Länge von 1, sodass Sie die Teilung am Ende weglassen und einfach Folgendes verwenden können:

=FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))

Jetzt können wir das verwenden, um den Ordnerpfad zu erhalten:

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))))

Hier ist der Ordnerpfad ohne das nachfolgende \

=LEFT(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))-1)

Und um nur den Dateinamen zu erhalten:

=MID(A1,FIND("@",SUBSTITUTE(A1,"\","@",LEN(A1)-LEN(SUBSTITUTE(A1,"\",""))))+1,LEN(A1))

Hier ist jedoch eine alternative Version, um alles rechts von der letzten Instanz eines bestimmten Charakters zu platzieren. Wenn Sie also dasselbe Beispiel verwenden, wird auch der Dateiname zurückgegeben:

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
Tigeravatar
quelle
24
Kopf drehen; Kopf dreht sich; Kopf drehen; "ok - will das nicht benutzen, ohne es zu verstehen, also ... ähm, ok, ähm ... warte was? whoah! wirklich? das ist genial! Ich bin zuversichtlich, dass ich in einigen Stunden nicht daran gedacht hätte wenn nicht Tage oder Wochen! " - +1, leider, weil +5 oder +10 alleine schwer zu machen sind --- wenn-du-feststeckst-Erklärung: (am Beispiel) SUBSTITUTEalle (3) Instanzen von \mit nichts (Länge der Zeichenfolge verkürzen) durch 3) -> dass \(der 3.) der letzte ist; Ersetzen Sie das durch etwas Einzigartiges und FINDdie Position dieses einzigartigen Charakters ... großartig ... danke!
Code Jockey
7
Es ist klug. Achten Sie nur darauf, dass die Zelle noch kein '@' enthält, da Sie sonst etwas anderes eingeben müssen. Sie können dies überprüfen =ISNUMBER(SEARCH("@",A1)), wie von @ gwin003 vorgeschlagen .
Geotheory
3
Ihre letzte Option, um alles rechts vom letzten Vorkommen zu extrahieren, wird sehr geschätzt, da ich die meiste Zeit nach dem "letzten Vorkommen von String x in String y" gesucht habe und mein Endziel wirklich darin bestand, alles zum Ziel zu bringen Recht auf dieses letzte Vorkommen.
SSilk
1
Warum 99? Nehmen Sie nur an, dass die Länge dieser verschiedenen Zeichenfolgen weniger als 99 beträgt? Siehe diese Antwort und diese Antwort , die keine solche Annahme machen.
Jean-François Corbett
2
Anstelle von "@" habe ich CHAR (9) (das Tabulatorzeichen) verwendet, da meine Daten ursprünglich aus tabulatorgetrennten Dateien stammen und ich garantiere, dass sie nicht in meinen Daten enthalten sind.
Josiah Yoder
28

Wie wäre es, eine benutzerdefinierte Funktion zu erstellen und diese in Ihrer Formel zu verwenden? VBA verfügt über eine integrierte Funktion, InStrRevdie genau das tut, wonach Sie suchen.

Fügen Sie dies in ein neues Modul ein:

Function RSearch(str As String, find As String)
    RSearch = InStrRev(str, find)
End Function

Und Ihre Funktion sieht folgendermaßen aus (vorausgesetzt, die ursprüngliche Zeichenfolge befindet sich in B1):

=LEFT(B1,RSearch(B1,"\"))
Keith Rust
quelle
2
Dies ist eine sehr vereinfachte, aber funktionierende Lösung. Wenn Sie in Ihrem Projekt VBA verwenden können, verwenden Sie dieses.
Patrick Hofman
7

tigeravatar und Jean-François Corbett schlugen vor, diese Formel zu verwenden, um die Zeichenfolge rechts vom letzten Vorkommen des Zeichens "\" zu generieren

=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))

Wenn das als Trennzeichen verwendete Zeichen das Leerzeichen "" ist, muss die Formel geändert werden in:

=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1)),"{","")

Es ist nicht zu erwähnen, dass das Zeichen "{" durch jedes Zeichen ersetzt werden kann, das im zu verarbeitenden Text nicht "normal" vorkommt.

Eugen Sumindan
quelle
Ich finde diese Lösung viel eleganter und verständlicher. Auch wenn Sie LEN (A1) mit einer Zahl multiplizieren, können Sie das n-te bis zum letzten Vorkommen erhalten, vorausgesetzt, Ihre ursprüngliche Zeichenfolge enthält keine Leerzeichen (was bei mir der Fall war)
Zlatin Zlatev
4

Ich habe gerade diese Lösung gefunden, es wurde kein VBA benötigt.

Finden Sie das letzte Vorkommen von "_" in meinem Beispiel;

=IFERROR(FIND(CHAR(1);SUBSTITUTE(A1;"_";CHAR(1);LEN(A1)-LEN(SUBSTITUTE(A1;"_";"")));0)

Von innen nach außen erklärt;

SUBSTITUTE(A1;"_";"") => replace "_" by spaces
LEN( *above* ) => count the chars
LEN(A1)- *above*  => indicates amount of chars replaced (= occurrences of "_")
SUBSTITUTE(A1;"_";CHAR(1); *above* ) => replace the Nth occurence of "_" by CHAR(1) (Nth = amount of chars replaced = the last one)
FIND(CHAR(1); *above* ) => Find the CHAR(1), being the last (replaced) occurance of "_" in our case
IFERROR( *above* ;"0") => in case no chars were found, return "0"

Hoffe das war hilfreich.

Herr dich
quelle
3

Mit dieser von mir erstellten Funktion können Sie die letzte Instanz einer Zeichenfolge innerhalb einer Zeichenfolge finden.

Sicher, die akzeptierte Excel-Formel funktioniert, aber es ist viel zu schwer zu lesen und zu verwenden. Irgendwann muss man in kleinere Stücke ausbrechen, damit es gewartet werden kann. Meine Funktion unten ist lesbar, aber das ist irrelevant, weil Sie sie in einer Formel mit benannten Parametern aufrufen. Dies macht die Verwendung einfach.

Public Function FindLastCharOccurence(fromText As String, searchChar As String) As Integer
Dim lastOccur As Integer
lastOccur = -1
Dim i As Integer
i = 0
For i = Len(fromText) To 1 Step -1
    If Mid(fromText, i, 1) = searchChar Then
        lastOccur = i
        Exit For
    End If
Next i

FindLastCharOccurence = lastOccur
End Function

Ich benutze es so:

=RIGHT(A2, LEN(A2) - FindLastCharOccurence(A2, "\"))
Michael Z.
quelle
2

In Anbetracht eines Teils eines Kommentars von @SSilk war mein Endziel wirklich, alles rechts von diesem letzten Ereignis zu machen. Ein alternativer Ansatz mit einer sehr einfachen Formel besteht darin, eine Spalte (sagen wir A) von Zeichenfolgen und auf die Kopie (sagen wir ) zu kopieren Spalte B) Suchen und Ersetzen anwenden. Nehmen wir zum Beispiel das Beispiel:Drive:\Folder\SubFolder\Filename.ext

Finde was

Dies gibt zurück, was (hier Filename.ext) nach der letzten Instanz des ausgewählten Zeichens (hier \) übrig bleibt, was manchmal ohnehin das Ziel ist, und erleichtert das Finden der Position des letzten solchen Zeichens mit einer kurzen Formel wie:

=FIND(B1,A1)-1
pnuts
quelle
1

Ich bin etwas spät zur Party, aber vielleicht könnte das helfen. Der Link in der Frage hatte eine ähnliche Formel, aber meine verwendet die IF () - Anweisung, um Fehler zu beseitigen.

Wenn Sie keine Angst vor Strg + Umschalt + Eingabetaste haben, können Sie mit einer Array-Formel ziemlich gut umgehen.

Zeichenfolge (in Zelle A1): "one.two.three.four"

Formel:

{=MAX(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)))}  use Ctrl+Shift+Enter

Ergebnis: 14

Zuerst,

ROW($1:$99)

Gibt ein Array von Ganzzahlen von 1 bis 99 zurück : {1,2,3,4,...,98,99}.

Nächster,

MID(A1,ROW($1:$99),1)

Gibt ein Array von Zeichenfolgen mit einer Länge von 1 zurück, die in der Zielzeichenfolge gefunden wurden, und gibt leere Zeichenfolgen zurück, nachdem die Länge der Zielzeichenfolge erreicht wurde: {"o","n","e",".",..."u","r","","",""...}

Nächster,

IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99))

vergleicht jedes Element im Array mit der Zeichenfolge "." und gibt entweder den Index des Zeichens in der Zeichenfolge oder FALSE zurück:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Zuletzt,

=MAX(IF(MID(I16,ROW($1:$99),1)=".",ROW($1:$99)))

Gibt den Maximalwert des Arrays zurück: 14

Vorteile dieser Formel sind, dass sie kurz und relativ einfach zu verstehen ist und keine eindeutigen Zeichen erfordert.

Nachteile sind die erforderliche Verwendung von Strg + Umschalt + Eingabetaste und die Begrenzung der Zeichenfolgenlänge. Dies kann mit einer unten gezeigten Variation umgangen werden, aber diese Variation verwendet die OFFSET () -Funktion, die eine flüchtige (read: slow) Funktion ist.

Ich bin mir nicht sicher, wie schnell diese Formel im Vergleich zu anderen ist.

Variationen:

=MAX((MID(A1,ROW(OFFSET($A$1,,,LEN(A1))),1)=".")*ROW(OFFSET($A$1,,,LEN(A1)))) works the same way, but you don't have to worry about the length of the string

=SMALL(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd occurrence of the match

=LARGE(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)),2) determines the 2nd-to-last occurrence of the match

=MAX(IF(MID(I16,ROW($1:$99),2)=".t",ROW($1:$99))) matches a 2-character string **Make sure you change the last argument of the MID() function to the number of characters in the string you wish to match!
Stadem
quelle
0

Eine einfache Möglichkeit, dies in VBA zu tun, ist:

YourText = "c:\excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))
Landelin Delcoucq
quelle
0

Sehr spät zur Party, aber eine einfache Lösung ist die Verwendung von VBA, um eine benutzerdefinierte Funktion zu erstellen.

Fügen Sie die Funktion zu VBA im Arbeitsbuch, Arbeitsblatt oder einem VBA-Modul hinzu

Function LastSegment(S, C)
    LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function

Dann die Zellformel

=lastsegment(B1,"/")

in einer Zelle und die in Zelle B1 zu durchsuchende Zeichenfolge füllen die Zelle mit dem Text, der dem letzten "/" von Zelle B1 folgt. Keine Längenbeschränkung, keine obskuren Formeln. Der einzige Nachteil, den ich mir vorstellen kann, ist die Notwendigkeit einer makrofähigen Arbeitsmappe.

Jede Benutzer-VBA-Funktion kann auf diese Weise aufgerufen werden, um einen Wert an eine Zellenformel zurückzugeben, einschließlich als Parameter für eine integrierte Excel-Funktion.

Wenn Sie die Funktion häufig verwenden, sollten Sie prüfen, ob das Zeichen nicht in der Zeichenfolge enthalten ist, die Zeichenfolge leer ist usw.

user8512894
quelle
0

Zelle A1 = find/the/position/of/the last slash

Eine einfache Möglichkeit besteht darin, den Text umzukehren und dann wie gewohnt den ersten Schrägstrich zu finden. Jetzt können Sie die Länge des Volltextes abzüglich dieser Zahl ermitteln.

Wie so:

=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1

Dies gibt 21 zurück, die Position des letzten /

Richard
quelle
REVERSETEXTist keine Standard-Excel-Formel
d219