【问题标题】:Excel: last character/string match in a stringExcel:字符串中的最后一个字符/字符串匹配
【发布时间】:2013-09-04 15:02:04
【问题描述】:

有没有一种有效的方法来使用基函数来识别字符串中最后一个字符/字符串匹配? IE。不是字符串的最后一个字符/字符串,而是一个字符/字符串最后一次出现字符串中的位置。 Searchfind 都从左到右工作,所以如果没有冗长的递归算法,我想不出如何应用。而this solution 现在似乎已经过时了。

【问题讨论】:

  • 因为我想要最后一个实例的位置,例如时期 ”。”在字符串“one.two.three.four”中
  • 有趣的是,错误阅读问题如何获得投票
  • 我想说从另一个角度来看,这意味着其他人也不明白你在你的问题中的意思,所以认为这个建议是正确的解决方案......甚至你的选择的答案以“我想我明白你的意思”开头...不是批评,而是请求旨在使您的问题更易于理解以帮助人们更轻松地回答。
  • 我应该将示例添加到问题中,但我认为这足以将其与关于字符串最后一个字符的查询区分开来:searchfind 都是查询字符串 content,'match'是一个标准术语,加上链接的例子。

标签: excel excel-formula


【解决方案1】:

我想我明白你的意思。例如,假设您想要以下字符串中最右边的 \(存储在单元格 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)))

【讨论】:

  • 头晕目眩;摇头;头部旋转; “好吧——不明白就不想使用它,所以……呃呃呃呃呃呃……等等什么?哇!真的?那是天才!我有信心在几个小时内我不会想到这一点如果不是几天或几周!” - +1,遗憾的是,因为 +5 或 +10 很难靠我自己完成 --- 如果你被卡住了解释:(使用示例)SUBSTITUTE 所有(3)个 \ 实例什么都没有(将字符串的长度缩短 3)-> \(第三个)是最后一个;用独特的东西替换它,FIND 那个独特角色的位置......太棒了......谢谢!
  • 这很聪明。只需要注意该单元格尚未包含“@”,否则您将需要使用其他内容。您可以使用=ISNUMBER(SEARCH("@",A1))as proposed by @gwin003 进行检查。
  • 非常感谢您提取最后一次出现右侧的所有内容的最后一个选项,因为大部分时间我一直在寻找“字符串 y 中最后一次出现的字符串 x”,这是我的最终目标真的是让一切都回到最后一次发生的正确。
  • 为什么是99?您是否只是假设这些各种字符串的长度小于 99?请参阅this answerthis answer,它们没有做出这样的假设。
  • 我使用CHAR(9)(制表符)代替了“@”,因为我的数据最初来自制表符分隔的文件,并且我保证它不会出现在我的数据中。
【解决方案2】:

如何创建一个自定义函数并在您的公式中使用它? VBA 有一个内置函数InStrRev,它完全符合您的要求。

把它放到一个新模块中:

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

你的函数看起来像这样(假设原始字符串在 B1 中):

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

【讨论】:

  • 这是一个非常简单但有效的解决方案。如果您可以在项目中使用一些 VBA,请使用这个。
【解决方案3】:

新答案 | 2022 年 3 月 31 日:

有了更新的功能,答案就更短了。在撰写测试版时,但可能在不久的将来广泛可用,我们可以使用TEXTBEFORE()

=LEN(TEXTBEFORE(A2,B2,-1))+1

这里的技巧是第三个参数告诉函数检索我们在第二个参数中给出的子字符串的最后一次出现。在编写此函数时,默认情况下仍区分大小写,可以通过可选的第四个参数来处理。


原答案 | 2020 年 17 月 6 日:

随着新版本的 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 的长期解决方案stackoverflow.com/a/18617720/1156245
  • 注意:虽然我的建议会在粗略的代码高尔夫中获胜,但在大量使用时并不总是建议使用数组。但是,它确实具有我试图明确提及的其他好处。这使得@Tigeravatar 的答案和以前一样重要!
  • 成功了。谢谢!
【解决方案4】:

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 次出现,前提是您的原始字符串不包含空格(对我来说就是这种情况)
【解决方案5】:

刚想出这个解决方案,不需要 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"

希望这对您有所帮助。

【讨论】:

    【解决方案6】:

    你可以使用我创建的这个函数在字符串中查找字符串的最后一个实例。

    公认的 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, "\"))
    

    【讨论】:

      【解决方案7】:

      考虑到@SSilk 发表的评论的一部分我的最终目标确实是将所有内容都放在最后一次出现的右侧一个非常简单的公式的替代方法是复制一列(比如A)字符串和副本(比如ColumnB)应用查找和替换。举个例子:Drive:\Folder\SubFolder\Filename.ext

      这将返回在选择任何字符的最后一个实例(此处为\)之后剩余的内容(此处为Filename.ext),这有时是无论如何的目标,并有助于使用简短的公式找到最后一个此类字符的位置,例如:

      =FIND(B1,A1)-1
      

      【讨论】:

        【解决方案8】:

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

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

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

        公式:

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

        结果:1​​4

        首先,

        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!
        

        【讨论】:

          【解决方案9】:

          在较新版本的 Excel(2013 及更高版本)中,快速填充可能是一种简单快捷的解决方案,请参阅:Using Flash Fill in Excel

          【讨论】:

            【解决方案10】:

            在 VBA 中执行此操作的一种简单方法是:

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

            【讨论】:

              【解决方案11】:

              聚会很晚,但一个简单的解决方案是使用 VBA 创建自定义函数。

              在工作簿、工作表或 VBA 模块中将函数添加到 VBA

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

              然后是单元格公式

              =lastsegment(B1,"/")
              

              在一个单元格中,并且要在单元格 B1 中搜索的字符串将使用单元格 B1 中最后一个“/”后面的文本填充该单元格。 没有长度限制,没有晦涩的公式。 我认为唯一的缺点是需要启用宏的工作簿。

              可以通过这种方式调用任何用户 VBA 函数以将值返回到单元格公式,包括作为内置 Excel 函数的参数。

              如果您要大量使用该函数,您需要检查字符不在字符串中的情况,然后字符串为空白等。

              【讨论】:

                【解决方案12】:

                对于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。

                【讨论】:

                  【解决方案13】:

                  如果您只是在寻找字符“~”的最后一个实例的位置,那么 =len(substitute(String,"~",""))+1

                  我确定有版本可以处理字符串的最后一个实例,但我必须重新开始工作。

                  【讨论】:

                    【解决方案14】:

                    单元格A1 = find/the/position/of/the last slash

                    简单的方法是反转文本,然后正常查找第一个斜线。现在你可以得到全文的长度减去这个数字。

                    像这样:

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

                    这将返回 21,即最后一个 / 的位置

                    【讨论】:

                    • REVERSETEXT 不是标准的 Excel 公式
                    猜你喜欢
                    • 1970-01-01
                    • 2018-10-27
                    • 2021-08-17
                    • 1970-01-01
                    • 1970-01-01
                    • 2023-03-08
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    相关资源
                    最近更新 更多