有没有一种有效的方法来使用基本函数来识别字符串中的最后一个字符/字符串匹配?即不是字符串的最后一个字符/字符串,而是一个字符/字符串在字符串中最后出现的位置。 Search
并且find
两者都是从左到右工作的,所以如果没有冗长的递归算法,我想不出如何应用。而这个解决方案现在似乎已经过时了。
14 回答
我想我明白你的意思。例如,假设您想要以下字符串中最右边的 \(存储在单元格 A1 中):
驱动器:\文件夹\子文件夹\文件名.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)))
如何创建自定义函数并在公式中使用它?VBA 有一个内置函数 ,InStrRev
它完全符合您的要求。
把它放在一个新模块中:
Function RSearch(str As String, find As String)
RSearch = InStrRev(str, find)
End Function
您的函数将如下所示(假设原始字符串在 B1 中):
=LEFT(B1,RSearch(B1,"\"))
新版本的 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"
希望这会有所帮助。
您可以使用我创建的这个函数在字符串中查找字符串的最后一个实例。
当然,公认的 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, "\"))
考虑到@SSilk发表的评论的一部分, 我的最终目标确实是将所有内容都放在最后一次出现的右侧,一种非常简单的公式的替代方法是复制一列(比如A
)字符串并在副本上(比如ColumnB) 应用查找和替换。举个例子:Drive:\Folder\SubFolder\Filename.ext
这将返回在Filename.ext
选择任何字符(此处)的最后一个实例之后剩余的内容(此处\
),这有时是目标,并有助于使用简短公式找到最后一个此类字符的位置,例如:
=FIND(B1,A1)-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!
在较新版本的 Excel(2013 及更高版本)中,快速填充可能是一种简单快捷的解决方案,请参阅: 在 Excel 中使用快速填充 。
对于 in 中的字符串A1
和 in 中的子字符串B1
,请使用:
=XMATCH(B1,MID(A1,SEQUENCE(LEN(A1)),LEN(B1)),,-1)
从内向外工作,MID(A1,SEQUENCE(LEN(A1)),LEN(B1))
将字符串拆分A1
为一个动态的子字符串数组,每个子字符串的长度为B1
. 为了找到最后一次出现的 substring的位置B1
,我们使用XMATCH
它的Search_mode
参数设置为 -1。
聚会很晚,但一个简单的解决方案是使用 VBA 创建自定义函数。
将函数添加到工作簿、工作表或 VBA 模块中的 VBA
Function LastSegment(S, C)
LastSegment = Right(S, Len(S) - InStrRev(S, C))
End Function
然后是单元格公式
=lastsegment(B1,"/")
在单元格中,要在单元格 B1 中搜索的字符串将使用单元格 B1 中最后一个“/”后面的文本填充单元格。没有长度限制,没有晦涩的公式。我认为唯一的缺点是需要启用宏的工作簿。
任何用户 VBA 函数都可以通过这种方式调用以将值返回到单元格公式,包括作为内置 Excel 函数的参数。
如果您要大量使用该函数,则需要检查字符不在字符串中的情况,然后字符串为空白等。
在 VBA 中执行此操作的一种简单方法是:
YourText = "c:\excel\text.txt"
xString = Mid(YourText, 2 + Len(YourText) - InStr(StrReverse(YourText), "\" ))
如果您只是在寻找字符“~”的最后一个实例的位置,那么 =len(substitute(String,"~",""))+1
我确定有版本可以与字符串的最后一个实例一起使用,但我必须重新开始工作。
细胞A1 = find/the/position/of/the last slash
简单的方法是反转文本,然后正常查找第一个斜杠。现在你可以得到全文的长度减去这个数字。
像这样:
=LEN(A1)-FIND("/",REVERSETEXT(A1),1)+1
这将返回 21,即最后一个 / 的位置