You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift正则处理Git Diff变更内容未获预期结果求助

Parsing Git Diff Content Between @@ Markers in Swift (macOS)

Hey there! Let's work through your regex issue with extracting content from Git diffs in Swift. I remember how confusing regex can be when dealing with line breaks and structured formats like diffs—so let's break this down step by step.

Why Your Hardcoded Regex Failed

The main problems with your hardcoded pattern are:

  1. It's rigid: You're matching exact line numbers, which won't work for dynamic diffs with changing line ranges.
  2. No support for line breaks: By default, Swift's regex treats . as matching only non-newline characters. So .* stops at the first line break, which means it can't capture multi-line content between markers.

Solution 1: Split the Diff (Simpler for Beginners)

Instead of regex, start by splitting the entire diff string on the @@ marker. This avoids dealing with complex pattern matching and is easy to debug:

let diffContent = """
@@ -24,7 +24,7 @@
First segment content here—includes newlines\tand tabs!
@@ -33,7 +33,7 @@
Second segment content
@@ -49,9 +49,9 @@
Third segment content with multiple lines
@@ -95,9 +95,9 @@
Fourth segment content (everything after the last marker)
"""

// Split the diff by @@, then filter out empty/whitespace-only segments
let rawSegments = diffContent.components(separatedBy: "@@").filter {
    !$0.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
}

// Extract the content after each marker's line number section
var finalSegments: [String] = []
for segment in rawSegments {
    // Find the first newline (marks the end of the @@ line)
    if let newlineIndex = segment.firstIndex(of: "\n") {
        let content = segment[newlineIndex...].trimmingCharacters(in: .newlines)
        finalSegments.append(content)
    }
}

// finalSegments now contains your 4 desired segments!
print(finalSegments)

This works because splitting on @@ gives us chunks starting with the line range (like -24,7 +24,7 ) followed by the actual content. We just need to strip off that line range part to get the content we want.


Solution 2: Flexible Regex (For More Control)

If you prefer using regex, we'll need to write a pattern that handles line breaks and matches dynamic line ranges. Here's how:

import Foundation

let diffContent = """
@@ -24,7 +24,7 @@
First segment content here—includes newlines\tand tabs!
@@ -33,7 +33,7 @@
Second segment content
@@ -49,9 +49,9 @@
Third segment content with multiple lines
@@ -95,9 +95,9 @@
Fourth segment content (everything after the last marker)
"""

do {
    // Regex pattern breakdown:
    // - `@@ -\d+,\d+ \+\d+,\d+ @@`: Matches any @@ line (handles dynamic line numbers)
    // - `([\s\S]*?)`: Captures all characters (including newlines) non-greedily
    // - `(?=@@|\Z)`: Stops capturing when it hits the next @@ or the end of the string
    let pattern = #"@@ -\d+,\d+ \+\d+,\d+ @@([\s\S]*?)(?=@@|\Z)"#
    let regex = try NSRegularExpression(pattern: pattern)
    let fullRange = NSRange(diffContent.startIndex..., in: diffContent)
    
    // Extract all matching segments
    let matches = regex.matches(in: diffContent, range: fullRange)
    let finalSegments = matches.map { match in
        let contentRange = match.range(at: 1)
        let content = String(diffContent[Range(contentRange, in: diffContent)!])
        return content.trimmingCharacters(in: .newlines)
    }
    
    print(finalSegments)
} catch {
    print("Regex error: \(error.localizedDescription)")
}

The [\s\S] trick matches every character (whitespace and non-whitespace), which lets us capture multi-line content. The non-greedy *? ensures we don't accidentally capture content past the next @@ marker.


Final Notes

  • The split method is great for quick, straightforward parsing—no regex knowledge required.
  • The regex method is more flexible if you need to handle edge cases (like diffs with no trailing content after the last marker).

内容的提问来源于stack exchange,提问作者PruitIgoe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:41:22