Excel:字符串中的最后一个字符/字符串匹配


187

有没有一种有效的方法使用基本函数来识别字符串中的最后一个字符/字符串匹配?即不是最后一个字符/字符串字符串,但字符/字符串最后出现的位置一个字符串。 Searchfind两个工作由左到右,所以我想不出如何在不长的递归算法应用。现在,此解决方案似乎已过时。


3
因为我想要例如句号“”的最后一个实例的位置。在字符串“ one.two.three.four”中
geotheory 2013年

6
有趣的

1
我想从另一个角度看待它,这意味着其他人也也不理解您在问题中的意思,因此认为该建议是正确的解决方案。即使您选择的答案也始于“我认为我明白您的意思” ...不是批评,而是要求使您的问题更易于理解,以帮助人们更轻松地回答。
约翰·布斯托斯

我应该将示例添加到问题中,但是我认为足以将其与关于字符串的最终字符的查询区分开:search并且find两个查询字符串content,'match'是一个标准术语以及链接的示例。
geotheory 2013年

Answers:


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的东西,以及那个独特角色的位置...太棒了,谢谢!
赛马会

7
这很聪明。只需注意该单元格中尚未包含“ @”,否则您将需要使用其他内容。您可以检查使用=ISNUMBER(SEARCH("@",A1))所建议的@ gwin003
geotheory,2014年

3
非常感谢您最后一次提取所有最后出现的事件的选项,因为大多数时候我一直在寻找“字符串y在字符串y中最后一次出现的事件”,所以我的最终目标实际上是将所有内容都提取到最后发生的权利。
SSilk

1
为什么99呢 您是否只是假设这些各种字符串的长度小于99?看到这个答案这个答案,没有这样的假设。
让·弗朗索瓦·科贝特

2
我使用的是CHAR(9)(制表符),而不是“ @”,因为我的数据最初来自制表符分隔的文件,并且可以保证它不会出现在我的数据中。
Josiah Yoder 2015年

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。
Patrick Hofman

7

tigeravatar和Jean-FrançoisCorbett建议使用此公式来生成最后一个出现“ \”字符的字符串

=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 发表的Comment的一部分,我的最终目标实际上是使所有内容都出现在最后一次出现的右边,一种具有非常简单公式的替代方法是复制A字符串列(例如),然后复制副本(例如ColumnB)应用查找和替换。举个例子:Drive:\Folder\SubFolder\Filename.ext

找什么

这将返回在Filename.ext选择了任何字符的最后一个实例(此处为)之后剩余的内容(此处为\),这有时仍然是目标,并且可以通过较短的公式(例如:)来找到最后一个此类字符的位置:

=FIND(B1,A1)-1

1

我参加聚会有点晚了,但这也许可以帮上忙。问题中的链接具有类似的公式,但我的使用IF()语句来消除错误。

如果您不惧怕Ctrl + Shift + Enter,则可以使用数组公式做得很好。

字符串(在单元格A1中):“一。二。三。四”

式:

{=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创建自定义功能。

在WorkBook,Worksheet或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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.