如何提取文本字符串中的文本

问题描述 投票:0回答:6

我有一个简单的问题,我希望在不使用 VBA 的情况下解决它,但如果这是解决它的唯一方法,那就这样吧。

我有一个包含多行(均为一列)的文件。每行都有如下所示的数据:

1 7.82E-13 >gi|297848936|参考|XP_00| 4-氢氧化物 gi|297338191|gb|23343|随机随机

2 5.09E-09 >gi|168010496|参考|xp_00| 2-丙酮酸

等等...

我想要的是某种方法来提取以“gi|”开头的数字字符串并以“|”结尾。对于某些行,这可能意味着多达 5 个 gi 编号,而对于其他行,则只有 1 个。

我希望输出看起来像这样:

297848936,297338191

168010496

等等...

excel vba excel-formula worksheet-function
6个回答
62
投票

这是使用正则表达式对象的非常灵活的 VBA 答案。该函数的作用是提取它找到的每个子组匹配(括号内的内容),并用您想要的任何字符串分隔(默认为“,”)。您可以在这里找到有关正则表达式的信息:http://www.regular-expressions.info/

您可以这样称呼它,假设第一个字符串位于 A1 中:

=RegexExtract(A1,"gi[|](\d+)[|]")

因为这会查找所有出现的“gi|”后面跟着一系列数字,然后是另一个“|”,对于你问题的第一行,这会给你这个结果:

297848936, 297338191

只需将其运行到列中即可完成!

Function RegexExtract(ByVal text As String, _
                      ByVal extract_what As String, _
                      Optional separator As String = ", ") As String

Dim allMatches As Object
Dim RE As Object
Set RE = CreateObject("vbscript.regexp")
Dim i As Long, j As Long
Dim result As String

RE.pattern = extract_what
RE.Global = True
Set allMatches = RE.Execute(text)

For i = 0 To allMatches.count - 1
    For j = 0 To allMatches.Item(i).submatches.count - 1
        result = result & (separator & allMatches.Item(i).submatches.Item(j))
    Next
Next

If Len(result) <> 0 Then
    result = Right$(result, Len(result) - Len(separator))
End If

RegexExtract = result

End Function

9
投票

这是(假设数据在 A 列)

=VALUE(LEFT(RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2),
FIND("|",RIGHT(A1,LEN(A1) - FIND("gi|",A1) - 2)) -1 ))

不是最好的公式,但它可以提取数字。

我刚刚注意到,因为每行有两个值,输出用逗号分隔。您需要检查是否有第二个匹配项、第三个匹配项等,以使其适用于每个单元格的多个数字。

参考您的确切样本(假设每个单元格最多有 2 个值),以下代码将起作用:

=IF(ISNUMBER(FIND("gi|",$A1,FIND("gi|", $A1)+1)),CONCATENATE(LEFT(RIGHT($A1,LEN($A1)
- FIND("gi|",$A1) - 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ), 
", ",LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1) 
- 2),FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1,FIND("gi|", $A1)+1) - 2)) 
-1 )),LEFT(RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2),
FIND("|",RIGHT($A1,LEN($A1) - FIND("gi|",$A1) - 2)) -1 ))

丑怎么样? VBA 解决方案可能更适合您,但我将把这个留给您。

要达到 5 个数字,请研究模式并在公式中手动递归。它会变得很长!


3
投票

我可能会首先使用将文本转换为列向导在

|
分隔符上拆分数据。 在 Excel 2007 中,位于数据选项卡上的数据工具组,然后选择文本到列。指定 Other:
|
作为分隔符。

从您发布的示例数据来看,执行此操作后,数字将全部位于同一列中,因此您可以删除不需要的列。


2
投票

由于其他人提出了没有 VBA 的解决方案...我将介绍确实使用的解决方案。现在,您决定使用它还是不使用它。

刚刚看到@Issun 提出了正则表达式的解决方案,非常好!无论哪种方式,都将仅使用“简单”VBA 为问题提供“适度”的解决方案。

Option Explicit
Option Base 0

Sub findGi()

    Dim oCell As Excel.Range
    Set oCell = Sheets(1).Range("A1")

    'Loops through every row until empty cell
    While Not oCell.Value = ""

        oCell.Offset(0, 1).Value2 = GetGi(oCell.Value)
        Set oCell = oCell.Offset(1, 0)

    Wend

End Sub

Private Function GetGi(ByVal sValue As String) As String

    Dim sResult As String
    Dim vArray As Variant
    Dim vItem As Variant
    Dim iCount As Integer

    vArray = Split(sValue, "|")
    iCount = 0

    'Loops through the array...
    For Each vItem In vArray

        'Searches for the 'Gi' factor...
        If vItem Like "*gi" And UBound(vArray) > iCount + 1 Then

            'Concatenates the results...
            sResult = sResult & vArray(iCount + 1) & ","

        End If

        iCount = iCount + 1

    Next vItem

    'And removes trail comma
    If Len(sResult) > 0 Then

        sResult = Left(sResult, Len(sResult) - 1)

    End If

    GetGi = sResult

End Function

1
投票

在 Google Sheets 中打开 Excel 并使用正则表达式 REGEXEXTRACT

使用示例

=REGEXEXTRACT("My favorite number is 241, but my friend's is 17", "\d+")

提示:在此示例中,

REGEXEXTRACT
将返回
241
,因为它返回第一个匹配的案例。

就你而言

=REGEXEXTRACT(A1,"gi[|](\d+)[|]")

0
投票

我想从“a 12345678 90123450-b”中提取16位数字。通过删除空格和特殊字符。 excel 中的输出应为“1234567890123456”

© www.soinside.com 2019 - 2024. All rights reserved.