Excel: การจับคู่อักขระ / สตริงสุดท้ายในสตริง


187

มีวิธีที่มีประสิทธิภาพในการระบุการจับคู่อักขระ / สตริงล่าสุดในสตริงโดยใช้ฟังก์ชันพื้นฐานหรือไม่ เช่นไม่ใช่อักขระ / สตริงสุดท้ายของสตริง แต่ตำแหน่งของอักขระ / สตริงล่าสุดที่เกิดขึ้นในสตริง Searchและfindทั้งคู่ทำงานจากซ้ายไปขวาดังนั้นฉันจึงไม่สามารถคิดวิธีนำไปใช้โดยไม่ต้องใช้อัลกอริธึมวนซ้ำแบบยาว และวิธีนี้ดูเหมือนจะล้าสมัยไปแล้ว


3
เพราะฉันต้องการตำแหน่งของอินสแตนซ์สุดท้ายของช่วงเวลาเช่น "" ในสตริง "one.two.three.four"
geotheory

6
ขบขันว่าการอ่านคำถามที่ผิดพลาดทำให้ได้รับการโหวตมากขึ้น
geotheory

1
ฉันว่าดูจากมุมมองอื่นหมายถึงคนอื่นยังไม่เข้าใจสิ่งที่คุณหมายถึงในคำถามของคุณและคิดว่าคำแนะนำคือทางออกที่ถูกต้อง ... แม้แต่คำตอบที่คุณเลือกก็เริ่มด้วย "ฉันคิดว่าฉัน เข้าใจในสิ่งที่คุณหมายถึง "... ไม่ใช่คำวิจารณ์ แต่เป็นคำขอให้ตั้งคำถามให้เข้าใจง่ายขึ้นเพื่อช่วยให้ผู้คนตอบคำถามได้ง่ายขึ้น
John Bustos

ฉันควรเพิ่มตัวอย่างให้กับคำถาม แต่ฉันคิดว่ามีเพียงพอที่จะแยกความแตกต่างนี้จากแบบสอบถามเกี่ยวกับอักขระสุดท้ายของสตริง: searchและเนื้อหาfindสตริงข้อความค้นหาทั้งคู่ 'จับคู่' เป็นคำมาตรฐานรวมถึงตัวอย่างที่เชื่อมโยง
geotheory

คำตอบ:


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

ไดรฟ์: \ โฟลเดอร์ \ โฟลเดอร์ย่อย \ 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ตำแหน่งของตัวละครที่ไม่เหมือนใคร ... สุดยอด ... ขอบคุณ!
รหัส Jockey

7
มันฉลาด เพียงแค่ต้องระวังว่าเซลล์นั้นไม่มี '@' อยู่แล้วมิฉะนั้นคุณจะต้องย่อยด้วยอย่างอื่น คุณสามารถตรวจสอบการใช้=ISNUMBER(SEARCH("@",A1)), ที่เสนอโดย @
geotheory

3
ตัวเลือกสุดท้ายของคุณสำหรับการแยกทุกอย่างทางด้านขวาของการเกิดครั้งสุดท้ายนั้นได้รับความนิยมอย่างมากเพราะส่วนใหญ่ฉันได้มองหา "การเกิดขึ้นครั้งสุดท้ายของสตริง x ภายในสตริง y" เป้าหมายสุดท้ายของฉันคือการทำให้ทุกอย่างเป็นจริง ด้านขวาของการเกิดขึ้นครั้งสุดท้าย
SSilk

1
ทำไม99? คุณแค่สมมติว่าความยาวของสตริงต่างๆเหล่านี้น้อยกว่า 99 หรือไม่? ดูคำตอบนี้และคำตอบนี้ที่ไม่มีข้อสันนิษฐานดังกล่าว
Jean-François Corbett

2
แทนที่จะเป็น "@" ฉันใช้CHAR (9) (อักขระแท็บ) เนื่องจากเดิมข้อมูลของฉันมาจากไฟล์ที่คั่นด้วยแท็บและฉันรับประกันว่ามันจะไม่อยู่ในข้อมูลของฉัน
Josiah Yoder

28

วิธีการเกี่ยวกับการสร้างฟังก์ชั่นที่กำหนดเองและใช้ในสูตรของคุณ? VBA มีฟังก์ชันในตัวInStrRevซึ่งทำสิ่งที่คุณต้องการอย่างแท้จริง

ใส่สิ่งนี้ในโมดูลใหม่:

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

และฟังก์ชั่นของคุณจะมีลักษณะเช่นนี้ (สมมติว่าสตริงต้นฉบับอยู่ใน B1):

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

2
นี่เป็นวิธีแก้ปัญหาที่ง่าย แต่ก็ใช้งานได้ หากคุณสามารถใช้ VBA บางอย่างในโครงการของคุณให้ใช้ VBA นี้
แพทริคฮอฟแมน

7

tigeravatar และ Jean-François Corbett แนะนำให้ใช้สูตรนี้เพื่อสร้างสตริงที่ถูกต้องของการเกิดขึ้นครั้งสุดท้ายของอักขระ "\"

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

หากอักขระที่ใช้เป็นตัวคั่นคือช่องว่าง "" สูตรจะต้องเปลี่ยนเป็น:

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

ไม่จำเป็นต้องพูดถึงอักขระ "{" สามารถถูกแทนที่ด้วยอักขระใด ๆ ที่ไม่ "ปกติ" เกิดขึ้นในข้อความที่จะประมวลผล


ฉันพบว่าวิธีนี้เป็นวิธีที่ฉลาดและเข้าใจได้ง่ายขึ้น นอกจากนี้หากคุณทวีคูณ LEN (A1) ด้วยตัวเลขคุณจะได้รับลำดับที่ n ถึงการเกิดครั้งล่าสุดหากสตริงต้นฉบับของคุณไม่มีช่องว่าง (ซึ่งเป็นกรณีของฉัน)
Zlatin Zlatev

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 เพื่อสร้างฟังก์ชั่นที่กำหนดเอง

เพิ่มฟังก์ชันให้กับ 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
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.