Excel: bir dizedeki son karakter / dize eşleşmesi


187

Temel işlevleri kullanarak bir karakter dizisindeki son karakter / karakter dizisini eşleştirmenin etkili bir yolu var mı? Yani değil son karakteri / dizesi içinde dize, ancak bir karakter / dizgenin en son karşılaştığınız pozisyonu içinde bir dize. Searchve findher ikisi de soldan sağa çalışır, bu yüzden uzun özyinelemeli algoritma olmadan nasıl uygulanacağını düşünemiyorum. Ve bu çözüm artık kullanılmıyor gibi görünüyor.


3
Çünkü örneğin "dönemin" son örneğinin konumunu istiyorum. dizede "one.two.three.four"
jeoloji

6
Sorunun hatalı bir şekilde okunmasının nasıl oy
topladığını eğlendirmek

1
Diğer perspektiften bak diyebilirim, bu da başkalarının da sorunuzda ne demek istediğinizi anlamadığını ve önerinin doğru çözüm olduğunu düşündüm ... Seçtiğiniz cevap bile "Sanırım ben Ne demek istediğini elde et "... Bir eleştiri değil, insanların daha kolay cevap vermesine yardımcı olmak için sorularınızı daha kolay anlaşılır hale getirme isteği.
John Bustos

Ben soruya örnek eklemeliydim, ama bu bir dizenin son karakteri hakkında bir sorgudan ayırmak için yeterli olduğunu düşünüyorum: searchve findher iki sorgu dize içeriği , 'maç' standart bir terim, artı bağlantılı örnek.
geotheory

Yanıtlar:


1

Excel'in yeni sürümleri ile yeni işlevler ve böylece yeni yöntemler geliyor. Eski sürümlerde kopyalanabilir olsa da (daha önce görmedim), bir Excel O365 olduğunda bir kullanabilirsiniz:

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

Bu aynı zamanda (çakışan) alt dizelerin son konumunu almak için de kullanılabilir:

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

Her ikisi de artık rastgele bir değiştirme karakteri kullanmamıza ve çakışan kalıplara izin vermemize rağmen, "olumsuz" bir dizinin kullanımıdır.


Not: Eski Excel sürümlerinde aynı davranışı aşağıdakilerden birini kullanarak zorlayabilirsiniz :

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

Aracılığıyla Girilen CtrlShiftEnterveya bir satır içinde kullanırken INDEXörtük kesişim kurtulmak için:

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

1
Tam tarihi onurlar @ tigeravatar'ın uzun zamandır devam eden çözümü stackoverflow.com/a/18617720/1156245
geotheory

Not: Benim önerim kabataslak kod-golf kazanacak olsa da, büyük miktarlarda kullanıldığında dizilerin kullanılması her zaman önerilmez. Ancak, açıkça bahsetmeye çalıştığım başka faydaları var. Bu, @ Tigeravatar'ın cevabını eskisi kadar alakalı hale getiriyor!
JvdV

345

Ne demek istediğini anlıyorum. Diyelim ki aşağıdaki dizede (A1 hücresinde depolanan) en sağdaki \ 'yi istiyorsunuz:

Sürücü: \ Klasör \ AltKlasör \ DosyaAdı

Son \ konumunu almak için şu formülü kullanırsınız:

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

Bu bize en sağdaki \ 24 karakterinde olduğunu söyler. Bunu "@" arayarak ve en son "\" yerine "@" yazarak yapar. Kullanarak sonuncusu belirler

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

Bu senaryoda, alt dize basitçe 1 uzunluğuna sahip "\" dir, böylece sonunda bölümü bırakabilir ve sadece şunu kullanabilirsiniz:

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

Şimdi bunu klasör yolunu almak için kullanabiliriz:

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

İşte izleyen klasör yolu \

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

Ve sadece dosya adını almak için:

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

Ancak, her şeyi belirli bir karakterin son örneğinin sağına getirmenin alternatif bir sürümü. Aynı örneğimizi kullanarak, bu dosya adını da döndürür:

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

24
baş döndürücü; baş dönmesi; baş döndürücü; "tamam - bunu anlamadan kullanmak istemiyorum, yani ... uh huh, tamam, uh huh ... bekle ne? whoah! gerçekten? bu dahi! Bunu birkaç saat içinde düşünmeyeceğime eminim günler ya da haftalar değilse! " - +1, maalesef, +5 veya +10'un kendi başıma yapılması zor --- eğer sıkışıp kalırsanız açıklama: (örneği kullanarak SUBSTITUTE) \hiçbir şey olmadan tüm (3) örnekleri (dize uzunluğunu kısaltın) 3'e göre) -> \(3'üncü) sonuncusu; bunu benzersiz bir şeyle ve FINDo eşsiz karakterin pozisyonuyla değiştirin ... harika ... teşekkürler!
Code Jckey

7
Zeki. Hücrenin zaten '@' içermediğine dikkat etmeniz yeterlidir, aksi takdirde başka bir şeyle uğraşmanız gerekir. Sen kullanarak kontrol edebilirsiniz =ISNUMBER(SEARCH("@",A1)), @ gwin003 önerdiği gibi .
geotheory

3
Son olayın sağındaki her şeyi ayıklamak için son seçeneğiniz çok takdir ediliyor, çünkü çoğu zaman "y dizesindeki x dizesinin son oluşumu" için aradığım, son hedefim her şeyi gerçekten bu son oluşumun hakkı.
SSilk

1
Neden 99? Sadece bu çeşitli dizelerin uzunluğunun 99'dan az olduğunu mu düşünüyorsunuz? Bu cevaba ve böyle bir varsayımda bulunmayan bu cevaba bakınız .
Jean-François Corbett

2
"@" Yerine, CHAR (9) (sekme karakteri) kullandım, çünkü verilerim sekmeyle ayrılmış dosyadan geliyor ve verilerimde olmayacağından eminim.
Josiah Yoder

28

Özel bir işlev oluşturmaya ve bunu formülünüzde kullanmaya ne dersiniz? VBA, InStrRevtam olarak aradığınızı yapan yerleşik bir işleve sahiptir .

Bunu yeni bir modüle yerleştirin:

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

Ve işleviniz şu şekilde görünecektir (orijinal dizenin B1'de olduğu varsayılarak):

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

2
Bu çok basit ama çalışan bir çözüm. Projenizde biraz VBA kullanabiliyorsanız bunu kullanın.
Patrick Hofman

7

tigeravatar ve Jean-François Corbett, bu formülü "\" karakterinin son tekrarında dize oluşturmak için kullanmanızı önerdi

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

Ayırıcı olarak kullanılan karakter boşluk "" ise, formül şu şekilde değiştirilmelidir:

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

Bahsetmeye gerek yok, "{" karakteri, işlenecek metinde "normalde" oluşmayacak herhangi bir karakterle değiştirilebilir.


Bu çözümü daha zarif ve anlaşılır buluyorum. Ayrıca, LEN'i (A1) bir sayıyla çarparsanız, orijinal
dizeniz

4

Bu çözümü buldum, VBA gerekmiyor;

Örneğimde en son "_" örneğini bulun;

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

İçini dışa açıkladı;

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"

Umarım bu yardımcı oldu.


3

Bir dize içindeki bir dizenin son örneğini bulmak için oluşturduğum bu işlevi kullanabilirsiniz.

Kabul edilen Excel formülünün çalıştığından emin olun, ancak okumak ve kullanmak çok zor. Bir noktada, daha küçük parçalara ayrılmanız gerekir, böylece bakım yapılabilir. Aşağıdaki işlevim okunabilir, ancak bu önemsiz çünkü adlandırılmış parametreleri kullanarak bir formülde çağırıyorsunuz. Bu onu kullanmayı kolaylaştırır.

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

Ben böyle kullanın:

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

2

@SSilk tarafından yapılan bir Yorumun bir kısmı göz önüne alındığında, son hedefim her şeyi son olayın sağına gerçekten çok basit bir formülle alternatif bir yaklaşım A, dizelerin bir sütununu (diyelim ) kopyalamak (kopyalamak Sütun B) Bul ve Değiştir'i uygulayın. Örneğin:Drive:\Folder\SubFolder\Filename.ext

Ne buldun

Bu Filename.ext, hangi karakterin seçildiğinin (burada \) son örneğinden sonra (burada ), bazen de yine de amaç olan ve bu gibi kısa bir formülle son bu karakterin konumunu bulmayı kolaylaştıran (burada ) geri döner :

=FIND(B1,A1)-1

1

Partiye biraz geç kaldım, ama belki bu yardımcı olabilir. Sorudaki bağlantı benzer bir formüle sahipti, ancak benimki hatalardan kurtulmak için IF () deyimini kullanıyor.

Ctrl + Shift + Enter'dan korkmuyorsanız, bir dizi formülü ile oldukça iyi yapabilirsiniz.

Dize (A1 hücresinde): "one.two.three.four"

Formül:

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

Sonuç: 14

İlk,

ROW($1:$99)

1 ile 99 arasında bir tamsayı dizisi döndürür: {1,2,3,4,...,98,99}.

Sonraki,

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

hedef dizede bulunan 1 uzunlukta dizelerden oluşan bir dizi döndürür, ardından hedef dizenin uzunluğuna ulaşıldıktan sonra boş dizeler döndürür: {"o","n","e",".",..."u","r","","",""...}

Sonraki,

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

dizideki her öğeyi "." dizesiyle karşılaştırır. ve dizedeki karakterin dizinini veya FALSE değerini döndürür:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Son,

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

dizinin maksimum değerini döndürür: 14

Bu formülün avantajları kısa, anlaşılması kolay ve benzersiz karakterler gerektirmemesidir.

Dezavantajlar Ctrl + Shift + Enter'ın gerekli kullanımı ve dize uzunluğundaki sınırlamadır. Bu, aşağıda gösterilen bir varyasyon ile çözülebilir, ancak bu varyasyon geçici (okuma: yavaş) işlevi olan OFFSET () işlevini kullanır.

Bu formülün diğerlerine kıyasla hızının ne olduğundan emin değilim.

Varyasyonlar:

=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

VBA'da bunu yapmanın basit bir yolu:

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

0

Partiye çok geç, ancak basit bir çözüm özel bir işlev oluşturmak için VBA kullanıyor.

İşlevi Çalışma Kitabı, Çalışma Sayfası veya VBA Modülündeki VBA'ya ekleme

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

Sonra hücre formülü

=lastsegment(B1,"/")

bir hücrede ve B1 hücresinde aranacak dize, hücreyi B1 hücresinden son "/" karakterini takip eden metinle doldurur. Uzunluk sınırı yok, belirsiz formül yok. Düşünebileceğim sadece olumsuz bir makro özellikli çalışma kitabına ihtiyaç olduğunu.

Herhangi bir kullanıcı VBA İşlevi, yerleşik bir Excel işlevine parametre de dahil olmak üzere hücre formülüne bir değer döndürmek için bu şekilde çağrılabilir.

İşlevi ağır bir şekilde kullanacaksanız, karakter dizede olmadığında, dizenin boş olduğu vb. Durumları kontrol etmek isteyeceksiniz.


0

Hücre A1 = find/the/position/of/the last slash

Bunu yapmanın basit yolu metni tersine çevirip ilk eğik çizgiyi normal olarak bulmaktır. Şimdi tam metnin uzunluğunu eksi bu sayıdan alabilirsiniz.

Şöyle ki:

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

Bu, sonuncunun /


REVERSETEXTstandart bir Excel formülü değil
d219
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.