Excel: ultima corrispondenza carattere / stringa in una stringa


187

Esiste un modo efficiente per identificare l'ultima corrispondenza carattere / stringa in una stringa usando le funzioni di base? Cioè non l'ultimo carattere / stringa della stringa, ma la posizione dell'ultima occorrenza di un carattere / stringa in una stringa. Searched findentrambi funzionano da sinistra a destra, quindi non riesco a pensare come applicare senza un lungo algoritmo ricorsivo. E questa soluzione ora sembra obsoleta.


3
Perché voglio la posizione dell'ultima istanza, ad esempio, del periodo "." nella stringa "one.two.three.four"
geotheory

6
Divertente come una lettura errata della domanda porti a voti più
alti

1
Direi che guardalo dall'altra prospettiva, significa che anche altre persone non hanno capito cosa volevi dire nella tua domanda e quindi ho pensato che il suggerimento fosse la soluzione corretta ... Anche la tua risposta selezionata è iniziata con "Penso di aver ottieni quello che vuoi dire "... Non una critica, ma piuttosto una richiesta per mirare a rendere le tue domande più facili da capire per aiutare le persone a rispondere più facilmente.
John Bustos,

Avrei dovuto aggiungere l'esempio alla domanda, ma penso che ci fosse abbastanza per distinguerlo da una query sul carattere finale di una stringa: searched findentrambi i contenuti della stringa di query , "match" è un termine standard, oltre all'esempio collegato.
geotheory

Risposte:


1

Con le versioni più recenti di Excel arrivano nuove funzioni e quindi nuovi metodi. Sebbene sia replicabile nelle versioni precedenti (ma non l'ho mai visto prima), quando si ha Excel O365 è possibile utilizzare:

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

Questo può anche essere usato per recuperare l'ultima posizione di sottostringhe (sovrapposte):

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

Sebbene ciò ci consenta di non utilizzare più un carattere di sostituzione arbitrario e di consentire schemi sovrapposti, il "rovescio della medaglia" è l'utilizzo di un array.


Nota: è possibile forzare lo stesso comportamento nelle versioni precedenti di Excel tramite entrambi

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

Inserito CtrlShiftEntero usando un inline INDEXper sbarazzarsi dell'intersezione implicita:

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

1
Penso che questa eredita il segno di spunta ora, anche se tutti gli onori storici appartengono @ tigeravatar di soluzione di lunga data stackoverflow.com/a/18617720/1156245
geotheory

Nota: anche se il mio suggerimento sarebbe vincente in abbozzato code-golf, l'uso di array non è sempre raccomandato se usato in grandi quantità. Tuttavia, ha altri vantaggi che ho cercato di menzionare esplicitamente. Questo rende la risposta di @Tigeravatar altrettanto rilevante di prima!
JvdV,

345

Penso di capire cosa intendi. Diciamo ad esempio che vuoi il più a destra \ nella seguente stringa (che è memorizzata nella cella A1):

Drive: \ Folder \ SubFolder \ Nomefile.est

Per ottenere la posizione dell'ultimo \, utilizzare questa formula:

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

Questo ci dice che il più a destra \ è nel personaggio 24. Lo fa cercando "@" e sostituendo l'ultimo "\" con un "@". Determina l'ultimo usando

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

In questo scenario, la sottostringa è semplicemente "\" che ha una lunghezza di 1, quindi alla fine è possibile interrompere la divisione e utilizzare semplicemente:

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

Ora possiamo usarlo per ottenere il percorso della cartella:

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

Ecco il percorso della cartella senza il trascinamento \

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

E per ottenere solo il nome file:

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

Tuttavia, ecco una versione alternativa per ottenere tutto a destra dell'ultima istanza di un personaggio specifico. Quindi, usando il nostro stesso esempio, questo restituirebbe anche il nome del file:

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

24
rotazione della testa; testa che gira; rotazione della testa; "ok - non voglio usarlo senza capirlo, quindi ... eh, ok, eh ... aspetta cosa? whoah! davvero? è geniale! Sono fiducioso che non ci avrei pensato tra diverse ore se non giorni o settimane! " - +1, purtroppo, perché +5 o +10 sono difficili da fare da soli --- if-are-stuck-spiegazione: (usando l'esempio) SUBSTITUTEtutte le (3) istanze di \con niente (accorciare la lunghezza della stringa per 3) -> quello \(il terzo) è l'ultimo; sostituiscilo con qualcosa di unico e FINDla posizione di quel personaggio unico ... fantastico ... grazie!
Codice Jockey

7
È intelligente. Devi solo stare attento che la cella non contiene già "@", altrimenti dovrai sostituirla con qualcos'altro. Puoi controllare usando =ISNUMBER(SEARCH("@",A1)), come proposto da @ gwin003 .
geoteca

3
La tua ultima opzione per estrarre tutto a destra dell'ultima occorrenza è molto apprezzata perché la maggior parte delle volte ho cercato "l'ultima occorrenza della stringa x nella stringa y", il mio obiettivo finale è stato davvero quello di portare tutto al diritto di quest'ultima ricorrenza.
SSilk,

1
Perché 99? Stai solo supponendo che la lunghezza di queste varie stringhe sia inferiore a 99? Vedi questa risposta e questa risposta che non fanno tale ipotesi.
Jean-François Corbett,

2
Invece di "@", ho usato CHAR (9) (il carattere di tabulazione), poiché i miei dati originariamente provengono da file delimitati da tabulazione e sono sicuro che non saranno nei miei dati.
Josiah Yoder,

28

Che ne dici di creare una funzione personalizzata e utilizzarla nella tua formula? VBA ha una funzione integrata InStrRev, che fa esattamente quello che stai cercando.

Metti questo in un nuovo modulo:

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

E la tua funzione sarà simile a questa (supponendo che la stringa originale sia in B1):

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

2
Questa è una soluzione molto semplicistica ma funzionante. Se puoi usare un po 'di VBA nel tuo progetto, usa questo.
Patrick Hofman,

7

tigeravatar e Jean-François Corbett hanno suggerito di usare questa formula per generare la stringa a destra dell'ultima occorrenza del carattere "\"

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

Se il carattere utilizzato come separatore è spazio "", la formula deve essere modificata in:

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

Non è necessario menzionare, il carattere "{" può essere sostituito con qualsiasi carattere che "normalmente" non si verifichi nel testo da elaborare.


Trovo questa soluzione molto più elegante e comprensibile. Inoltre, se moltiplichi LEN (A1) per un numero, puoi ottenere l'ennesima occorrenza, a condizione che la stringa originale non contenga spazi (che è stato il mio caso)
Zlatin Zlatev

4

Ho appena trovato questa soluzione, non è necessario VBA;

Trova l'ultima occorrenza di "_" nel mio esempio;

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

Spiegato dentro e fuori;

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"

Spero sia stato utile.


3

È possibile utilizzare questa funzione che ho creato per trovare l'ultima istanza di una stringa all'interno di una stringa.

Sicuramente la formula di Excel accettata funziona, ma è troppo difficile da leggere e usare. Ad un certo punto devi irrompere in pezzi più piccoli, quindi è mantenibile. La mia funzione di seguito è leggibile, ma è irrilevante perché la chiami in una formula usando parametri denominati. Questo rende l'utilizzo semplice.

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

Lo uso così:

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

2

Considerando una parte di un commento fatto da @SSilk il mio obiettivo finale è stato davvero quello di portare tutto a destra dell'ultima occorrenza, un approccio alternativo con una formula molto semplice è copiare una colonna (diciamo A) di stringhe e sulla copia (dire Colonna B) applica Trova e sostituisci. Ad esempio prendendo l'esempio:Drive:\Folder\SubFolder\Filename.ext

Trovare cosa

Ciò restituisce ciò che rimane (qui Filename.ext) dopo l'ultima istanza di qualunque personaggio sia scelto (qui \) che a volte è comunque l'obiettivo e facilita la ricerca della posizione dell'ultimo personaggio con una formula breve come:

=FIND(B1,A1)-1

1

Sono un po 'in ritardo alla festa, ma forse questo potrebbe aiutare. Il collegamento nella domanda aveva una formula simile, ma il mio utilizza l'istruzione IF () per eliminare gli errori.

Se non hai paura di Ctrl + Maiusc + Invio, puoi fare abbastanza bene con una formula di matrice.

String (nella cella A1): "one.two.three.four"

Formula:

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

Risultato: 14

Primo,

ROW($1:$99)

restituisce un array di numeri interi da 1 a 99: {1,2,3,4,...,98,99}.

Il prossimo,

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

restituisce una matrice di stringhe di 1 lunghezza trovate nella stringa di destinazione, quindi restituisce stringhe vuote dopo aver raggiunto la lunghezza della stringa di destinazione: {"o","n","e",".",..."u","r","","",""...}

Il prossimo,

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

confronta ogni elemento dell'array con la stringa "." e restituisce l'indice del carattere nella stringa o FALSO:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Scorso,

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

restituisce il valore massimo dell'array: 14

I vantaggi di questa formula è che è breve, relativamente facile da capire e non richiede caratteri unici.

Gli svantaggi sono l'uso richiesto di Ctrl + Maiusc + Invio e la limitazione della lunghezza della stringa. Questo può essere risolto con una variazione mostrata di seguito, ma quella variazione usa la funzione OFFSET () che è una funzione volatile (leggi: lenta).

Non sono sicuro di quale sia la velocità di questa formula rispetto ad altre.

variazioni:

=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

Un modo semplice per farlo in VBA è:

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

0

Molto tardi per la festa, ma una soluzione semplice sta usando VBA per creare una funzione personalizzata.

Aggiungi la funzione a VBA nel Workbook, nel foglio di lavoro o in un modulo VBA

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

Quindi la formula cellulare

=lastsegment(B1,"/")

in una cella e la stringa da cercare nella cella B1 popolerà la cella con il testo che segue l'ultimo "/" dalla cella B1. Nessun limite di lunghezza, nessuna formula oscura. L'unico aspetto negativo che posso pensare è la necessità di una cartella di lavoro abilitata per le macro.

Qualsiasi funzione VBA utente può essere chiamata in questo modo per restituire un valore a una formula di cella, incluso come parametro una funzione Excel incorporata.

Se hai intenzione di utilizzare pesantemente la funzione, ti consigliamo di verificare il caso in cui il carattere non è nella stringa, quindi la stringa è vuota, ecc.


0

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

un modo semplice per farlo è invertire il testo e trovare normalmente la prima barra. Ora puoi ottenere la lunghezza del testo completo meno questo numero.

Così:

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

Questo restituisce 21, la posizione dell'ultimo /


REVERSETEXTnon è una formula standard di Excel
d219
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.