Excel: останній символ / рядок збігаються в рядку


187

Чи є ефективний спосіб визначити останній збіг символів / рядків у рядку за допомогою базових функцій? Тобто не останній символ / рядок з рядка, але становище останнього входження символу / струни в рядку. Searchі findобидва працюють зліва направо, тому я не можу думати, як застосувати без тривалого рекурсивного алгоритму. І це рішення зараз здається застарілим.


3
Тому що я хочу позицію останньої інстанції, наприклад, періоду ". у рядку "one.two.three.four"
геотеорія

6
Забавно, як помилкове читання питання збирає голоси
геотерія

1
Я б сказав, погляньте на це з іншої точки зору, це означає, що інші люди також не зрозуміли, що ви мали на увазі під своїм запитанням, і тому зрозуміли, що пропозиція є правильним рішенням ... Навіть ваша обрана відповідь почалася з "Я думаю, що я отримайте те, що ви маєте на увазі "... Не критика, а швидше прохання прагнути зробити ваші запитання легшими для розуміння, щоб допомогти людям легше відповідати.
Джон Бустос

Я мав би додати приклад до запитання, але я думаю, що цього було достатньо, щоб відрізнити це від запиту про остаточний символ рядка: searchі findобидва вмісту рядка запиту "збіг" - це стандартний термін, а також пов'язаний приклад.
геотеорія

Відповіді:


1

З новішими версіями excel з'являються нові функції і, отже, нові методи. Хоча це можна повторити в старих версіях (але я його ще не бачив), коли в Excel O365 можна використовувати:

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

Це також можна використовувати для отримання останнього положення (перекриваються) підрядів:

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

Незважаючи на те, що це дозволяє нам більше не використовувати довільний символ заміни, а це дозволяє перекривати шаблони, "недоліком" є використання масиву.


Примітка. Ви можете змусити таку саму поведінку у старих версіях Excel через будь-яку

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

Введено через CtrlShiftEnterабо використовуючи рядок, INDEXщоб позбутися від неявного перетину:

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

1
Я думаю , що це успадковує кліщ зараз, хоча повні історичні почесті належать @ tigeravatar з давнім рішенням stackoverflow.com/a/18617720/1156245
geotheory

Примітка: Хоча моя пропозиція виграє в схематичному коді-гольфі, використання масивів не завжди рекомендується при використанні у великих кількостях. Однак у неї є й інші переваги, про які я намагався прямо вказати. Це робить відповідь від @Tigeravatar настільки ж актуальною, як і раніше!
JvdV

345

Я думаю, я розумію, що ти маєш на увазі. Скажімо, наприклад, що ви хочете найправіше \ у наступному рядку (який зберігається у комірці A1):

Диск: \ Folder \ SubFolder \ Filename.ext

Щоб отримати позицію останнього \, ви використовуєте цю формулу:

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

Це говорить нам, що найправіше \ є у символі 24. Це робиться шляхом пошуку "@" та заміщення самого останнього "\" на "@". Останнє визначає за допомогою використання

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

У цьому випадку підрядок - це просто "\", який має довжину 1, так що ви можете залишити поділ наприкінці і просто використовувати:

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

Тепер ми можемо використовувати це для отримання шляху до папки:

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

Ось шлях до папки без трейлінгу \

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

І щоб отримати лише ім'я файлу:

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

Однак, ось альтернативна версія отримання всього праворуч від останнього екземпляра конкретного символу. Отже, використовуючи наш той же приклад, це також поверне ім'я файлу:

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

24
обертання голови; обертання голови; обертання голови; "гаразд - не хочеш використовувати це, не розуміючи цього, так ... е-е-е, гаразд, е-а-а ... чекай, що? хм! насправді? це геній! Я впевнений, що не подумав би про це через кілька годин якщо не дні чи тижні! " - +1, на жаль, тому що +5 або +10 важко зробити самостійно --- якщо-ти застряг-пояснення: (використовуючи приклад) SUBSTITUTEвсі (3) екземпляри \нічого (скоротити довжину рядка по 3) -> що \(3-й) - останній; замініть це чимось унікальним і FINDпозиція цього унікального персонажа ... дивовижна ... дякую!
Code Jockey

7
Це розумно. Потрібно просто остерігатися, що комірка ще не містить "@", інакше вам потрібно буде підкорити щось інше. Ви можете перевірити, використовуючи =ISNUMBER(SEARCH("@",A1)), як запропонував @ gwin003 .
геотеорія

3
Ваш останній варіант вилучення всього праворуч від останнього виникнення дуже вдячний, тому що більшу частину часу я шукав "останнє виникнення рядка x в рядку y", моєю кінцевою метою було насправді довести все до право від останнього виникнення.
SSilk

1
Чому 99? Ви просто припускаєте, що довжина цих різних рядків менше 99? Дивіться цю відповідь і цю відповідь, які не припускають такого припущення.
Жан-Франсуа Корбетт

2
Замість "@" я використав CHAR (9) (символ вкладки), оскільки мої дані спочатку надходять із файлу з обмеженими вкладками, і я гарантую, що він не буде в моїх даних.
Йосія Йодер

28

Як щодо створення власної функції та використання її у вашій формулі? VBA має вбудовану функцію InStrRev, яка робить саме те, що ви шукаєте.

Помістіть це в новий модуль:

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

І ваша функція буде виглядати приблизно так (припустимо, що початковий рядок знаходиться в B1):

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

2
Це дуже спрощене, але робоче рішення. Якщо ви можете використовувати VBA у своєму проекті, використовуйте цей.
Патрік Хофман

7

Тігераватар і Жан-Франсуа Корбет запропонували використовувати цю формулу для створення правого рядка останнього виникнення символу "\"

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

Якщо символом, який використовується як роздільник, є пробіл, "", то формулу потрібно змінити на:

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

Не потрібно згадувати, символ "{" може бути замінений будь-яким символом, який "нормально" не виникає в тексті для обробки.


Я вважаю це рішення способом більш елегантним та зрозумілим. Крім того, якщо ви помножите LEN (A1) на число, ви можете отримати n-е в останнє виникнення, за умови, що ваша оригінальна рядок не містить пробілів (що було для мене)
Златін Златев,

4

Щойно придумали це рішення, не потрібна VBA;

Знайдіть останнє значення "_" на моєму прикладі;

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

Пояснено зсередини;

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"

Сподіваюся, що це було корисно.


3

Ви можете використовувати цю функцію, яку я створив, щоб знайти останній екземпляр рядка в рядку.

Впевнений, що прийнята формула Excel працює, але читати та використовувати її занадто важко. У якийсь момент вам доведеться розбитись на більш дрібні шматки, щоб це було можливо. Моя функція нижче читається, але це не має значення, оскільки ви називаєте її у формулі, використовуючи названі параметри. Це робить його простим.

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

Я використовую це так:

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

2

Враховуючи частину коментаря, зробленого @SSilk, моєю кінцевою метою справді було отримати все праворуч від останнього виникнення , альтернативним підходом із дуже простою формулою є копіювання стовпця (скажімо A) рядків та копіювання (скажімо СтовпецьB) застосувати Знайти та замінити. Наприклад, взявши приклад:Drive:\Folder\SubFolder\Filename.ext

Знайти що

Це повертає те, що залишається (тут Filename.ext) після останнього екземпляра будь-якого символу, обраного (тут \), що іноді є ціллю так чи інакше і полегшує пошук позиції останнього такого символу з короткою формулою, наприклад:

=FIND(B1,A1)-1

1

Я трохи запізнююся на вечірку, але, можливо, це могло б допомогти. Посилання у питанні мала аналогічну формулу, але моя використовує оператор IF () для позбавлення від помилок.

Якщо ви не боїтеся Ctrl + Shift + Enter, ви можете добре виконати формулу масиву.

Рядок (у комірці A1): "one.two.three.four"

Формула:

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

Результат: 14

Перший,

ROW($1:$99)

повертає масив цілих чисел від 1 до 99: {1,2,3,4,...,98,99}.

Далі,

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

повертає масив рядків довжиною 1 довжини, знайдений у цільовому рядку, а потім повертає порожні рядки після досягнення довжини цільової рядки: {"o","n","e",".",..."u","r","","",""...}

Далі,

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

порівнює кожен елемент у масиві з рядком ". і повертає або індекс символу в рядку, або FALSE:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Останнє,

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

повертає максимальне значення масиву: 14

Переваги цієї формули полягають у тому, що вона коротка, відносно проста для розуміння та не потребує унікальних символів.

Недоліками є необхідне використання Ctrl + Shift + Enter та обмеження довжини рядка. Це можна вирішити за допомогою варіанту, показаного нижче, але ця версія використовує функцію OFFSET (), яка є мінливою (читання: повільна) функцією.

Не впевнений, яка швидкість цієї формули проти інших.

Варіації:

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

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

0

Дуже пізно на вечірку, але просте рішення - використання VBA для створення власної функції.

Додайте функцію до VBA в робочу книгу, робочий лист або модуль VBA

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

Потім формула клітини

=lastsegment(B1,"/")

у комірці, а рядок, яку потрібно шукати в комірці B1, заповнить комірку текстом, що відкладає останнє "/" від комірки B1. Ні обмеження довжини, ні незрозумілих формул. Єдиним недоліком, на який я можу подумати, є необхідність роботи з макрокомандою.

Будь-яку функцію VBA користувача можна назвати таким чином, щоб повернути значення формулі комірки, включаючи як параметр вбудовану функцію Excel.

Якщо ви будете активно використовувати цю функцію, вам потрібно перевірити, чи немає символу в рядку, тоді рядок порожній і т.д.


0

Осередок A1 = find/the/position/of/the last slash

простий спосіб зробити це - перевернути текст, а потім знайти першу косу рису як звичайну. Тепер ви можете отримати довжину повного тексту за мінусом цього числа.

Так:

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

Це повертає 21, позицію останнього /


REVERSETEXTне є стандартною формулою Excel
d219
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.