有没有一种有效的方法来使用基本函数识别字符串中最后一个字符/字符串匹配?即不是字符串的最后一个字符/字符串,而是字符/字符串的最后出现位置在字符串中的位置。搜索和查找都是从左到右工作的,因此我无法想出如何应用它们而不需要冗长的递归算法。而且这个解决方案现在似乎已经过时。这个解决方案
有没有一种有效的方法来使用基本函数识别字符串中最后一个字符/字符串匹配?即不是字符串的最后一个字符/字符串,而是字符/字符串的最后出现位置在字符串中的位置。搜索和查找都是从左到右工作的,因此我无法想出如何应用它们而不需要冗长的递归算法。而且这个解决方案现在似乎已经过时。这个解决方案
我想我明白你的意思。比如说,你想要以下字符串中最右边的\
(该字符串存储在单元格A1
中):
Drive:\Folder\SubFolder\Filename.ext
\
的位置,您可以使用以下公式:=FIND("@",SUBSTITUTE(A1,"\","@",(LEN(A1)-LEN(SUBSTITUTE(A1,"\","")))/LEN("\")))
这告诉我们最右边的\
在第24
个字符处。它通过查找"@"
并将最后一个"\"
替换为"@"
来实现这一点。它使用以下方法确定最后一个:
(len(string)-len(substitute(string, substring, "")))/len(substring)
"\"
,因此您可以省略末尾的除法,直接使用:=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))
然而,如果您可以确保A1
中的字符串不包含单词之间重复的空格†,那么这里有一个获取特定字符最后一次出现右侧所有内容的替代版本。因此,使用我们相同的示例,这也将返回文件名:
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
† 因为这是TRIM
文档所述的内容(重点在于我):
从文本中删除除单词之间的单个空格外的所有空格。对从其他应用程序接收到可能具有不规则间距的文本使用TRIM。
由于文件名可能包含重复的空格,因此使用基于TRIM
的解决方案可能会导致将重复的空格替换为单个空格而得到不正确的结果。
FIND
该唯一字符的位置...真棒...谢谢! - Code Jockey=ISNUMBER(SEARCH("@",A1))
进行检查,如@gwin003所建议的。 - geotheory你可以创建一个自定义函数并在公式中使用。VBA内置了一个名为InStrRev
的函数,正好符合你的需求。
将以下代码放入新模块中:
Function RSearch(str As String, find As String)
RSearch = InStrRev(str, find)
End Function
假设原始字符串在B1中,那么您的函数将如下所示:
=LEFT(B1,RSearch(B1,"\"))
新答案 | 2022年3月31日:
随着越来越多的新功能,我们可以使用TEXTBEFORE()
函数。该函数目前处于BETA测试阶段,但很快将在未来广泛使用。
=LEN(TEXTBEFORE(A2,B2,-1))+1
原始回答 | 2020年6月17日:
随着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"),))
tigeravatar和Jean-François Corbett建议使用这个公式来生成在最后一个“\”字符右侧的字符串。
=TRIM(RIGHT(SUBSTITUTE(A1,"\",REPT(" ",LEN(A1))),LEN(A1)))
=SUBSTITUTE(RIGHT(SUBSTITUTE(A1," ",REPT("{",LEN(A1))),LEN(A1)),"{","")
我刚想出了这个解决方案,不需要使用 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"
Drive:\Folder\SubFolder\Filename.ext
此操作将返回所选择字符(此处为\
)的最后一个实例后面的内容(此处为Filename.ext
),这往往是我们想要的结果,而且还可以通过短小的公式方便地找到该字符的最后一个位置:
=FIND(B1,A1)-1
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, "\"))
对于字符串A1
中的子字符串B1
,请使用以下公式:
=XMATCH(B1,MID(A1,SEQUENCE(LEN(A1)),LEN(B1)),,-1)
从内向外操作,MID(A1,SEQUENCE(LEN(A1)),LEN(B1))
将字符串A1
拆分成一个动态数组,每个子字符串的长度均为B1
的长度。为了找到子字符串B1
的最后一次出现的位置,我们需要使用XMATCH
,并将其Search_mode
参数设置为-1。
{=MAX(IF(MID(A1,ROW($1:$99),1)=".",ROW($1:$99)))} use Ctrl+Shift+Enter
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!
search
和find
都是查询字符串内容的术语,“match”是一个标准术语,加上链接的示例。 - geotheory