Excel: khớp ký tự / chuỗi cuối cùng trong chuỗi


187

Có cách nào hiệu quả để xác định khớp / ký tự cuối cùng trong chuỗi bằng các hàm cơ sở không? Tức là không phải là ký tự / chuỗi cuối cùng của chuỗi, mà là vị trí xuất hiện cuối cùng của một ký tự / chuỗi trong chuỗi. Searchfindcả hai hoạt động từ trái sang phải để tôi không thể nghĩ cách áp dụng mà không cần thuật toán đệ quy dài. Và giải pháp này bây giờ có vẻ lỗi thời.


3
Bởi vì tôi muốn vị trí của ví dụ cuối cùng của khoảng thời gian "." trong chuỗi "one.two.three.four"
geotheory

6
Thật thú vị khi cách đọc sai của câu hỏi thu hút số phiếu bầu
geotheory

1
Tôi muốn nói hãy nhìn nó từ góc độ khác, điều đó có nghĩa là những người khác cũng không hiểu ý của bạn trong câu hỏi của bạn và vì vậy, gợi ý đó là giải pháp chính xác ... Ngay cả câu trả lời được chọn của bạn cũng bắt đầu bằng "Tôi nghĩ tôi hiểu ý bạn "... Không phải là một lời chỉ trích, mà là một yêu cầu nhằm mục đích làm cho câu hỏi của bạn dễ hiểu hơn để giúp mọi người trả lời dễ dàng hơn.
John Bustos

Tôi nên thêm ví dụ vào câu hỏi, nhưng tôi nghĩ có đủ để phân biệt điều này với truy vấn về ký tự cuối cùng của chuỗi: searchfindcả nội dung chuỗi truy vấn , 'khớp' là một thuật ngữ chuẩn, cộng với ví dụ được liên kết.
địa lý

Câu trả lời:


1

Với các phiên bản mới hơn của excel có các chức năng mới và do đó các phương thức mới. Mặc dù nó có thể nhân rộng trong các phiên bản cũ hơn (nhưng tôi chưa thấy nó trước đây), nhưng khi có Excel O365, người ta có thể sử dụng:

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

Điều này cũng có thể được sử dụng để lấy vị trí cuối cùng của các lớp nền (chồng chéo):

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

Trong khi cả hai điều này cho phép chúng ta không còn sử dụng một ký tự thay thế tùy ý và nó cho phép các mẫu chồng chéo, "nhược điểm" là việc sử dụng một mảng.


Lưu ý: Bạn có thể buộc hành vi tương tự trong các phiên bản Excel cũ hơn thông qua một trong hai

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

Đã nhập CtrlShiftEnterhoặc sử dụng nội tuyến INDEXđể thoát khỏi giao lộ ngầm:

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

1
Tôi nghĩ rằng điều này thừa hưởng tích tắc ngay bây giờ, mặc dù danh dự lịch sử đầy đủ thuộc về giải pháp lâu đời của @ tigeravatar stackoverflow.com/a/18617720/1156245
geotheory

Lưu ý: Trong khi đề xuất của tôi sẽ giành chiến thắng tại môn đánh gôn sơ sài, việc sử dụng mảng không phải lúc nào cũng được khuyến nghị khi sử dụng với số lượng lớn. Tuy nhiên, nó có những lợi ích khác mà tôi đã cố gắng đề cập rõ ràng. Điều này làm cho câu trả lời của @Tigeravatar vẫn có liên quan như trước đây!
JvdV

345

Tôi nghĩ rằng tôi hiểu ý bạn. Ví dụ, giả sử bạn muốn có hầu hết \ trong chuỗi sau (được lưu trữ trong ô A1):

Ổ đĩa: \ Thư mục \ SubFolder \ Filename.ext

Để có được vị trí cuối cùng \, bạn sẽ sử dụng công thức này:

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

Điều đó cho chúng ta biết phần lớn quyền \ nằm ở ký tự 24. Nó thực hiện điều này bằng cách tìm kiếm "@" và thay thế "\" cuối cùng bằng "@". Nó xác định cái cuối cùng bằng cách sử dụng

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

Trong trường hợp này, chuỗi con chỉ đơn giản là "\" có độ dài bằng 1, do đó bạn có thể rời khỏi phân chia ở cuối và chỉ cần sử dụng:

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

Bây giờ chúng ta có thể sử dụng nó để có được đường dẫn thư mục:

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

Đây là đường dẫn thư mục không có dấu \

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

Và để có được tên tệp:

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

Tuy nhiên, đây là một phiên bản thay thế của việc đưa mọi thứ về bên phải của phiên bản cuối cùng của một nhân vật cụ thể. Vì vậy, sử dụng ví dụ tương tự của chúng tôi, điều này cũng sẽ trả về tên tệp:

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

24
quay đầu; đầu spinnning; quay đầu; "ok - không muốn sử dụng cái này mà không hiểu nó, vì vậy ... uh huh, ok, uh huh ... chờ đợi cái gì? whoah! thực sự? đó là thiên tài! Tôi cảm thấy tự tin tôi sẽ không nghĩ về điều đó trong vài giờ nếu không phải ngày hay tuần! " - +1, thật đáng buồn, vì +5 hoặc +10 khó thực hiện theo cách riêng của tôi --- nếu bạn bị mắc kẹt - giải thích: (sử dụng ví dụ) SUBSTITUTEtất cả (3) trường hợp \không có gì (rút ngắn độ dài chuỗi bởi 3) -> rằng \(thứ 3) là cái cuối cùng; thay thế nó bằng một cái gì đó độc đáo và FINDvị trí của nhân vật độc đáo đó ... tuyệt vời ... cảm ơn!
Mã J Racer

7
Thật là thông minh. Chỉ cần lưu ý rằng ô không chứa '@' nếu không bạn sẽ cần phải phụ với thứ khác. Bạn có thể kiểm tra bằng cách sử dụng =ISNUMBER(SEARCH("@",A1)), như được đề xuất bởi @ gwin003 .
địa lý

3
Tùy chọn cuối cùng của bạn để trích xuất mọi thứ ở bên phải của lần xuất hiện cuối cùng được đánh giá cao bởi vì hầu hết thời gian tôi đã tìm kiếm "lần xuất hiện cuối cùng của chuỗi x trong chuỗi y", mục tiêu cuối cùng của tôi thực sự là đưa mọi thứ đến quyền của sự xuất hiện cuối cùng
SSilk

1
Tại sao 99? Bạn chỉ giả sử độ dài của các chuỗi khác nhau nhỏ hơn 99? Xem câu trả lời nàycâu trả lời này mà không có giả định như vậy.
Jean-François Corbett

2
Thay vì "@", tôi đã sử dụng CHAR (9) (ký tự tab), vì dữ liệu của tôi ban đầu đến từ tệp được phân định bằng tab và tôi đảm bảo rằng nó sẽ không nằm trong dữ liệu của tôi.
Josiah Yoder

28

Làm thế nào về việc tạo một chức năng tùy chỉnh và sử dụng chức năng đó trong công thức của bạn? VBA có chức năng tích hợp sẵn, InStrRevchính xác là những gì bạn đang tìm kiếm.

Đặt cái này trong một mô-đun mới:

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

Và hàm của bạn sẽ trông như thế này (giả sử chuỗi gốc nằm trong B1):

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

2
Đây là một giải pháp rất đơn giản nhưng làm việc. Nếu bạn có thể sử dụng một số VBA trong dự án của bạn, hãy sử dụng cái này.
Patrick Hofman

7

tigeravatar và Jean-François Corbett đề nghị sử dụng công thức này để tạo ra chuỗi bên phải của lần xuất hiện cuối cùng của ký tự "\"

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

Nếu ký tự được sử dụng làm dấu phân cách là dấu cách, "", thì công thức phải được thay đổi thành:

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

Không cần đề cập, ký tự "{" có thể được thay thế bằng bất kỳ ký tự nào không "bình thường" xảy ra trong văn bản để xử lý.


Tôi thấy giải pháp này thanh lịch và dễ hiểu hơn. Ngoài ra, nếu bạn nhân LEN (A1) với một số bạn có thể nhận được lần thứ n đến lần xuất hiện cuối cùng, miễn là chuỗi ban đầu của bạn không chứa khoảng trắng (đó là trường hợp của tôi)
Zlatin Zlatev

4

Chỉ cần đưa ra giải pháp này, không cần VBA;

Tìm sự xuất hiện cuối cùng của "_" trong ví dụ của tôi;

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

Giải thích từ trong ra ngoài;

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"

Hy vọng điều này là hữu ích.


3

Bạn có thể sử dụng hàm này do tôi tạo để tìm phiên bản cuối cùng của chuỗi trong chuỗi.

Chắc chắn công thức Excel được chấp nhận hoạt động, nhưng quá khó để đọc và sử dụng. Tại một số điểm, bạn phải chia thành các phần nhỏ hơn để có thể duy trì. Hàm của tôi dưới đây có thể đọc được, nhưng điều đó không liên quan vì bạn gọi nó trong một công thức sử dụng các tham số được đặt tên. Điều này làm cho việc sử dụng nó đơn giản.

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

Tôi sử dụng nó như thế này:

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

2

Xem xét một phần của Nhận xét do @SSilk đưa ra, mục tiêu cuối cùng của tôi thực sự là đưa mọi thứ về đúng với sự xuất hiện cuối cùng đó bằng một cách tiếp cận khác với một công thức rất đơn giản là sao chép một cột (nói A) chuỗi và trên bản sao (nói CộtB) áp dụng Tìm và Thay thế. Ví dụ lấy ví dụ:Drive:\Folder\SubFolder\Filename.ext

Tìm cái gì

Điều này trả về những gì còn lại (ở đây Filename.ext) sau trường hợp cuối cùng của bất kỳ ký tự nào được chọn (ở đây \) đôi khi là mục tiêu và tạo điều kiện tìm vị trí của ký tự cuối cùng với một công thức ngắn như:

=FIND(B1,A1)-1

1

Tôi đến bữa tiệc muộn một chút, nhưng có lẽ điều này có thể giúp ích. Liên kết trong câu hỏi có công thức tương tự, nhưng tôi sử dụng câu lệnh IF () để loại bỏ lỗi.

Nếu bạn không sợ Ctrl + Shift + Enter, bạn có thể làm khá tốt với công thức mảng.

Chuỗi (trong ô A1): "one.two.three.four"

Công thức:

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

Kết quả: 14

Đầu tiên,

ROW($1:$99)

trả về một mảng các số nguyên từ 1 đến 99 : {1,2,3,4,...,98,99}.

Kế tiếp,

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

trả về một chuỗi các chuỗi có độ dài 1 được tìm thấy trong chuỗi đích, sau đó trả về các chuỗi trống sau khi đạt được độ dài của chuỗi mục tiêu: {"o","n","e",".",..."u","r","","",""...}

Kế tiếp,

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

so sánh từng mục trong mảng với chuỗi "." và trả về chỉ mục của ký tự trong chuỗi hoặc FALSE:{FALSE,FALSE,FALSE,4,FALSE,FALSE,FALSE,8,FALSE,FALSE,FALSE,FALSE,FALSE,14,FALSE,FALSE.....}

Cuối cùng,

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

trả về giá trị tối đa của mảng: 14

Ưu điểm của công thức này là nó ngắn, tương đối dễ hiểu và không yêu cầu bất kỳ ký tự duy nhất.

Nhược điểm là yêu cầu sử dụng Ctrl + Shift + Enter và giới hạn về độ dài chuỗi. Điều này có thể được xử lý xung quanh với một biến thể được hiển thị bên dưới, nhưng biến thể đó sử dụng hàm OFFSET () là hàm biến động (đọc: chậm).

Không chắc chắn tốc độ của công thức này là gì so với những người khác.

Biến thể:

=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

Một cách đơn giản để làm điều đó trong VBA là:

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

0

Rất muộn cho bữa tiệc, nhưng Một giải pháp đơn giản là sử dụng VBA để tạo chức năng tùy chỉnh.

Thêm chức năng vào VBA trong WorkBook, Worksheet hoặc VBA Module

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

Sau đó, công thức tế bào

=lastsegment(B1,"/")

trong một ô và chuỗi được tìm kiếm trong ô B1 sẽ điền vào ô có văn bản theo dấu "/" cuối cùng từ ô B1. Không giới hạn chiều dài, không có công thức tối nghĩa. Nhược điểm duy nhất tôi có thể nghĩ là cần một bảng tính kích hoạt macro.

Bất kỳ Hàm VBA người dùng nào cũng có thể được gọi theo cách này để trả về giá trị cho công thức ô, bao gồm làm tham số cho hàm Excel dựng sẵn.

Nếu bạn định sử dụng chức năng nhiều, bạn sẽ muốn kiểm tra trường hợp khi ký tự không có trong chuỗi, thì chuỗi trống, v.v.


0

Tế bào A1 = find/the/position/of/the last slash

Cách đơn giản để làm điều đó là đảo ngược văn bản và sau đó tìm dấu gạch chéo đầu tiên như bình thường. Bây giờ bạn có thể nhận được độ dài của toàn văn trừ số này.

Thích như vậy:

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

Điều này trả về 21, vị trí cuối cùng /


REVERSETEXTkhông phải là một công thức Excel tiêu chuẩn
d219
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.