如何匹配字符串末尾的子串,然后只删除该子串?

How to match a substring at the end of a string, and then delete only that substring?

我在每个单元格中有一列文本,其中许多单元格的末尾都有字符串 null。如果单元格的内容以该字符串结尾,我想解析列中的每个单元格并从单元格中删除 just null

到目前为止,如果 null 和前面的单词之间有一个 space,我所写的内容成功地从末尾删除了 null,但删除了 整个单元格的 前面的单词和 null 之间没有 space 的内容。

Sub TruncateNulls()

    Dim strPattern As String: strPattern = "\w*null\b"
    Dim strReplace As String: strReplace = ""
    Dim regEx As New RegExp
    Dim strInput As String

    ActiveSheet.Range("A2").Select

    Do While ActiveCell.Value <> ""
        strInput = ActiveCell.Value

        With regEx
            .Global = False
            .MultiLine = True
            .IgnoreCase = True
            .Pattern = strPattern
        End With

        If regEx.Test(strInput) Then
            ActiveCell = regEx.Replace(strInput, strReplace)
        End If

        ActiveCell.Offset(1, 0).Select
    Loop

End Sub

示例输入数据:

words
null
wordsnull
words null
nullwords

需要的输出数据:

words

words
words
nullwords

我如何调整它以仅删除结尾 null,而不考虑前面的字符?

或者,我愿意使用 Excel 的 Find 功能,或搜索和替换 window 中的特定 wildcard/wildcard 组合,如果这些选项有效。

如果您更喜欢当前的方法,则需要将您的模式替换为

\s*null\s*$

regex demo

详情

  • \s* - 0+ whitespaces(如果不想跨行溢出,请将 \s 替换为 space 或 [^\S\r\n]
  • null - null 子字符串
  • \s* - 1个或多个白色spaces(见上面相同的注释)
  • $ - 行尾(将 .Multiline 标志设置为 False 以匹配字符串的结尾)。

在这种情况下,比正则表达式更简单的是使用 Right() 函数检查最后 4 个字符。您的代码可以减少到

Do While ActiveCell.Value <> ""
    strInput = ActiveCell.Value
    If Right(strInput, 4) = "null" Then
        ActiveCell.Value = Left(strInput, Len(strInput)-4)
    End If
    ActiveCell.Offset(1, 0).Select
Loop

据我了解,这也更有效(并且可以通过定义范围并将其值复制到数组来提高效率)。

使用 .Replace 和模式 \s*null$ 删除每个单元格末尾的所有匹配项。您还应该考虑将范围加载到数组中以缩短执行时间。

Sub TruncateNulls()
    Dim rg As Range, data()

    ' select the range to the last row
    Set rg = Range(Range("A2"), Range("A" & rows.Count).end(xlUp))

    ' load the data in an array
    data = rg.value

    ' replace each value with a regex
    ArrayReplace data, pattern:="\s*null$", replacement:=Empty

    ' write the array back to the sheet
    rg.value = data
End Sub


Sub ArrayReplace(data(), pattern As String, replacement As String)
    Dim re As New RegExp, r As Long, c As Long

    re.Global = True
    re.MultiLine = False
    re.IgnoreCase = True
    re.pattern = pattern

    For c = 1 To UBound(data, 2)
        For r = 1 To UBound(data, 1)
            If VarType(data(r, c)) = vbString Then
                data(r, c) = re.Replace(data(r, c), replacement)
            End If
        Next
    Next
End Sub