Excel: ostatni znak / ciąg pasuje do ciągu


187

Czy istnieje skuteczny sposób na identyfikację ostatniego dopasowania znaku / ciągu w ciągu za pomocą funkcji podstawowych? Czyli nie ostatni znak / string z łańcucha, ale pozycja ostatniego wystąpienia o charakterze / String jest w ciąg. Searchi findoba działają od lewej do prawej, więc nie mogę wymyślić, jak zastosować bez długiego algorytmu rekurencyjnego. I to rozwiązanie wydaje się przestarzała.


3
Ponieważ chcę pozycję ostatniej instancji np. Kropki „.” w ciągu „one.two.three.four”
— geotheory

6
Zabawne, jak błędne odczytanie pytania
— budzi

1
Powiedziałbym, że popatrz na to z innej perspektywy, to znaczy, że inni też nie rozumieli, co masz na myśli w twoim pytaniu, i dlatego doszedłem do wniosku, że sugestia była właściwym rozwiązaniem ... Nawet twoja wybrana odpowiedź zaczęła się od „Myślę, że ja rozumiem, co masz na myśli „... Nie krytyka, ale prośba o uczynienie twoich pytań łatwiejszymi do zrozumienia, aby ludzie mogli łatwiej odpowiedzieć.
— John Bustos

Powinienem był dodać przykład do pytania, ale myślę, że było wystarczająco, aby odróżnić to od zapytania dotyczącego końcowego znaku ciągu: searchi findzarówno w treści ciągu zapytania , „dopasowanie” jest terminem standardowym, plus połączony przykład.
— geotheory

Odpowiedzi:


1

Wraz z nowszymi wersjami programu Excel pojawiają się nowe funkcje, a tym samym nowe metody. Chociaż można go powielać w starszych wersjach (ale nie widziałem go wcześniej), gdy używa się programu Excel O365, można użyć:

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

Można to również wykorzystać do pobrania ostatniej pozycji (nakładających się) podciągów:

=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        |

Chociaż pozwala to nam nie używać już dowolnych znaków zastępczych i pozwala na nakładanie się wzorców, „minusem” jest użycie tablicy.


Uwaga: Możesz wymusić to samo zachowanie w starszych wersjach programu Excel za pomocą jednego z nich

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

Wprowadzone przez CtrlShiftEnterlub za pomocą wstawki, INDEXaby pozbyć się niejawnego skrzyżowania:

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

1
Myślę, że to dziedziczy teraz kleszcza, choć pełne historyczne zaszczyty należą do długoletniego rozwiązania @ tigeravatar stackoverflow.com/a/18617720/1156245
— geotheory

Uwaga: Chociaż moja sugestia wygrałaby podczas szkicowego golfa, użycie tablic nie zawsze jest zalecane, gdy jest używane w dużych ilościach. Ma jednak inne zalety, o których starałem się wyraźnie wspomnieć. To sprawia, że ​​odpowiedź @Tigeravatar jest tak samo aktualna jak wcześniej!
— JvdV

345

Myślę, że rozumiem o co ci chodzi. Powiedzmy na przykład, że chcesz najbardziej w prawo \ w następującym ciągu (który jest przechowywany w komórce A1):

Dysk: \ Folder \ Podfolder \ Nazwa pliku. Tekst

Aby uzyskać pozycję ostatniego \, użyłbyś tej formuły:

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

To mówi nam, że najbardziej na prawo \ jest znak 24. Czyni to, szukając „@” i zastępując ostatnie „\” znakiem „@”. Określa ostatni za pomocą

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

W tym scenariuszu podciąg to po prostu „\”, który ma długość 1, więc możesz zrezygnować z podziału na końcu i po prostu użyć:

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

Teraz możemy go użyć, aby uzyskać ścieżkę folderu:

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

Oto ścieżka do folderu bez końcowego \

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

Aby uzyskać tylko nazwę pliku:

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

Jednak tutaj jest alternatywna wersja przenoszenia wszystkiego na prawo od ostatniej instancji określonej postaci. Korzystając z tego samego przykładu, zwróciłoby to również nazwę pliku:

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

24
kręcenie głową; wirowanie głowy; kręcenie głową; „ok - nie chcę tego używać bez zrozumienia tego, więc… hmm, ok, hmm ... poczekaj co? whoah! naprawdę? to geniusz! Jestem pewien, że nie pomyślałbym o tym za kilka godzin jeśli nie dni lub tygodnie! ” - +1, niestety, ponieważ +5 lub +10 jest trudne do zrobienia na własną rękę --- jeśli utkniesz w objaśnieniu: (na przykładzie) SUBSTITUTEwszystkie (3) wystąpienia \bez niczego (skróć długość łańcucha o 3) -> że \(3.) jest ostatnim; zastąp to czymś wyjątkowym i FINDpozycją tej wyjątkowej postaci ... niesamowite ... dzięki!
— Code Jockey

7
To jest sprytne. Musisz tylko uważać, aby komórka nie zawierała już znaku „@”, w przeciwnym razie będziesz musiał zapisać coś innego. Możesz to sprawdzić za pomocą =ISNUMBER(SEARCH("@",A1)), zgodnie z propozycją @ gwin003 .
— geotheory

3
Twoja ostatnia opcja wyodrębnienia wszystkiego po prawej stronie ostatniego wystąpienia jest bardzo doceniana, ponieważ przez większość czasu szukałem „ostatniego wystąpienia ciągu x w ciągu y”, moim ostatecznym celem było doprowadzenie wszystkiego do prawo do ostatniego zdarzenia.
— SSilk

1
Dlaczego 99? Czy po prostu zakładasz, że długość tych różnych łańcuchów jest mniejsza niż 99? Zobacz tę odpowiedź i tę odpowiedź, które nie zakładają takiego założenia.
— Jean-François Corbett

2
Zamiast „@” użyłem CHAR (9) (znak tabulacji), ponieważ moje dane pierwotnie pochodzą z pliku rozdzielanego tabulatorami i jestem pewien, że nie będzie ich w moich danych.
— Josiah Yoder

28

Co powiesz na utworzenie niestandardowej funkcji i użycie jej w formule? VBA ma wbudowaną funkcję,InStrRev , która robi dokładnie to, czego szukasz.

Umieść to w nowym module:

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

A twoja funkcja będzie wyglądać tak (zakładając, że oryginalny ciąg znajduje się w B1):

=LEFT(B1,RSearch(B1,"\"))

2
To bardzo uproszczone, ale działające rozwiązanie. Jeśli możesz użyć VBA w swoim projekcie, użyj tego.
— Patrick Hofman,

7

tigeravatar i Jean-François Corbett zasugerowali użycie tej formuły do ​​wygenerowania ciągu znaków po ostatnim wystąpieniu znaku „\”

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

Jeśli znakiem używanym jako separator jest spacja „”, należy zmienić formułę na:

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

Nie trzeba wspominać, że znak „{” można zastąpić dowolnym znakiem, który „normalnie” nie występuje w przetwarzanym tekście.


Uważam to rozwiązanie za bardziej eleganckie i zrozumiałe. Również jeśli pomnożymy LEN (A1) przez liczbę, możemy uzyskać n-ty do ostatniego wystąpienia, pod warunkiem, że oryginalny ciąg nie zawiera spacji (co miało miejsce w moim przypadku)
— Zlatin Zlatev

4

Właśnie wymyśliłem to rozwiązanie, nie wymaga VBA;

Znajdź ostatnie wystąpienie „_” w moim przykładzie;

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

Wyjaśnione na lewą stronę;

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"

Mam nadzieję, że to było pomocne.


3

Możesz użyć tej funkcji, którą utworzyłem, aby znaleźć ostatnią instancję ciągu w ciągu.

Upewnij się, że przyjęta formuła programu Excel działa, ale jest zbyt trudna do odczytania i użycia. W pewnym momencie musisz podzielić się na mniejsze części, aby można było je utrzymać. Moja funkcja poniżej jest czytelna, ale to nie ma znaczenia, ponieważ wywołujesz ją w formule przy użyciu nazwanych parametrów. To sprawia, że ​​korzystanie z niego jest proste.

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

Używam tego w ten sposób:

=RIGHT(A2, LEN(A2) - FindLastCharOccurence(A2, "\"))

2

Biorąc pod uwagę część komentarza dokonanego przez @SSilk, moim ostatecznym celem było doprowadzenie wszystkiego do prawej strony tego ostatniego wystąpienia. Alternatywnym podejściem z bardzo prostą formułą jest skopiowanie kolumny (powiedzmy A) ciągów znaków i skopiowanie (powiedzmy) Kolumna B) zastosuj Znajdź i zamień. Na przykład biorąc przykład:Drive:\Folder\SubFolder\Filename.ext

Znajdź co

Zwraca to, co pozostaje (tutaj Filename.ext) po ostatnim wystąpieniu dowolnej postaci (tutaj \), co i tak czasami jest celem i ułatwia znalezienie pozycji ostatniej takiej postaci za pomocą krótkiej formuły, takiej jak:

=FIND(B1,A1)-1

1

Jestem trochę spóźniony na imprezę, ale może to może pomóc. Link w pytaniu miał podobną formułę, ale moja używa instrukcji IF (), aby pozbyć się błędów.

Jeśli nie boisz się klawiszy Ctrl + Shift + Enter, możesz całkiem dobrze poradzić sobie z formułą tablicową.

Ciąg (w komórce A1): „one.two.three.four”

Formuła:

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

Wynik: 14

Pierwszy,

ROW($1:$99)

zwraca tablicę liczb całkowitych od 1 do 99: {1,2,3,4,...,98,99} .

Kolejny,

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

zwraca tablicę ciągów o długości 1 znalezionych w ciągu docelowym, a następnie zwraca puste ciągi po osiągnięciu długości ciągu docelowego: {"o","n","e",".",..."u","r","","",""...}

Kolejny,

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

porównuje każdy element w tablicy z ciągiem „.” i zwraca indeks znaku w ciągu lub FAŁSZ:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Ostatni, ubiegły, zeszły,

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

zwraca maksymalną wartość tablicy: 14

Zaletą tej formuły jest to, że jest krótka, stosunkowo łatwa do zrozumienia i nie wymaga żadnych unikalnych znaków.

Wady to wymagane użycie Ctrl + Shift + Enter i ograniczenie długości łańcucha. Można to obejść za pomocą wariantu pokazanego poniżej, ale ta odmiana korzysta z funkcji OFFSET (), która jest funkcją zmienną (czytaj: wolno).

Nie jestem pewien, jaka jest szybkość tej formuły w porównaniu z innymi.

Wariacje:

=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!


0

Prostym sposobem na to w VBA jest:

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

0

Bardzo późno na imprezę, ale prostym rozwiązaniem jest użycie VBA do stworzenia niestandardowej funkcji.

Dodaj funkcję do VBA w skoroszycie, arkuszu lub module VBA

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

Następnie formuła komórkowa

=lastsegment(B1,"/")

w komórce, a ciąg do przeszukania w komórce B1 zapełni komórkę tekstem kończącym ostatnie „/” z komórki B1. Bez ograniczenia długości, bez niejasnych wzorów. Jedynym minusem jest to, że potrzebuję skoroszytu z obsługą makr.

W ten sposób można wywołać dowolną funkcję VBA użytkownika, aby zwrócić wartość do formuły komórkowej, w tym jako parametr do wbudowanej funkcji Excel.

Jeśli zamierzasz intensywnie korzystać z tej funkcji, powinieneś sprawdzić wielkość liter, gdy znak nie znajduje się w ciągu, a następnie ciąg jest pusty itp.


0

Komórka A1 = find/the/position/of/the last slash

prosty sposób to odwrócić tekst, a następnie normalnie znaleźć pierwszy ukośnik. Teraz możesz uzyskać długość pełnego tekstu minus ten numer.

Tak jak:

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

Zwraca 21, pozycję ostatniego /


REVERSETEXTnie jest standardową formułą Excela
— d219
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.