Swift 文件处理: 强迫症文本解析

本文介绍了如何使用 Swift 解析文本,整理 Xcode 代码库的文件结构,尤其是针对 AudioKit/Cookbook 库。通过正则表达式和递归处理,去除无效符号,去除最外层 Section,整理第一层和第二层数据,最终建立类名索引,为代码文件创建对应目录并移动。目前完成了文本解析部分,下一步计划根据类名匹配文件名。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

学习 Swift 三方库源代码的时候,Xcode 里面的目录结构,与实际工程的文件结构不一致

调试不方便

  • 一般 Xcode 里面看到的代码文件,是有层次的。文件夹里面的代码,都在一层,不好找

  • Xcode 里面看到的代码文件,一个文件夹下面的太多了,不够细致

根据代码里面的文件结构,创建相应的文件夹,把代码文件移入,好一些

有一点强迫症的感觉

本文完成第一步,文本解析

案例:

学习 AudioKit/AudioKit 有一个库 AudioKit/Cookbook,

本文整理他的代码

效果:

从这样

Form {
            Section(header: Text("Mini Apps")
                        .padding(.top, 20)) {
                Section {
                    
                    NavigationLink(destination: DrumsView()) { Text("Drum Pads") }
                    NavigationLink(destination: DrumSequencerView()) { Text("Drum Sequencer") }
                    NavigationLink(destination: DrumSynthesizersView()) { Text("Drum Synthesizers") }
                    NavigationLink(destination: GraphicEqualizerView()) { Text("Graphic Equalizer") }
                    NavigationLink(destination: MusicToyView()) { Text("Music Toy") }
                    
     /...

到这样:

0_0 : ["DrumsView", "DrumSequencerView", "DrumSynthesizersView", 
"GraphicEqualizerView", "MusicToyView", "Telephone", "TunerView", 
"NoiseGeneratorsView", "VocalTractView", "MIDIMonitorView"] 

// ...

解决:

思路:

把所有文件的类名,按照顺序找出来,用正则表达式简单

按照顺序找出所有的类名,建立层级,稍微麻烦

正则处理

本文的案例中,有嵌套代码,即有层级

例子中的 Section ,最多两层嵌套

先把最外层的 Section 中的代码,索引分块,

之后正则出条目,完

代码:

正则表达式,不好处理嵌套的内容,

嵌套的内容,一般使用递归,

案例中清楚其层级,两层 while 循环就好

第一步,去除无效符号

本文采用命令行程序,

加载文件

if let src = URL(string: "\(NSHomeDirectory())/Documents/Lalathon/src/ContentView.swift"){
    do {
        contents = try String(contentsOfFile: src.path)
       // print(contents ?? "")
    } catch {
        print(error)
    }
}


去除空格和换行

// 去除空格和换行
guard let info = contents?.replacingOccurrences(of: " ", with: "").replacingOccurrences(of: "\n", with: "") else{
    fatalError()
}

第 2 步,去除最外层的 section

采用的是字符串遍历,

首先碰到 “Section”, 遇到 “{”, 开始看 bracketCount 的值,

之后进入嵌套的 while 循环,

遇到 “{” , bracketCount + 1,

遇到 “}” , bracketCount - 1

当 bracketCount == 0, 就处理完了一个 最外层的 “Section”


struct TargetInfo{
    let start = "Section"
    let second: Character = "{"
    let end: Character = "}"
}


let target = TargetInfo()

func extract(content info: String) -> [String]{
    var i = 0
    let total = info.count

    var result = [String]()

    while i < total {
        
        
        let endIndex = i + target.start.count - 1
        if endIndex >= total{
            break
        }
        
        if let temp = info[i...endIndex], temp == target.start{

            var bracketCount = 0
            
            i += target.start.count - 1
            var beginIndex = 0
            first: while i < total {
                inner: switch info[i] {
                case target.second:
                    if bracketCount == 0{
                        beginIndex = i
                    }
                    bracketCount += 1
                case target.end:
                    bracketCount -= 1
                    if bracketCount == 0{
                        result.append(info[(beginIndex+1)...(i-1)] ?? "")
                        break inner
                    }
                default:
                    ()
                }
                i += 1
            }
            
        }
        
        i += 1
    }
    return result
}
第 3 步,整理第一层数据

之后,就是不断的 map, filter

先过滤,只取需要的数据,

这里用的关键词是 “NavigationLink”, 用其他的当然可以

var rawInfo = extract(content: info)

// filter

rawInfo = rawInfo.filter { (piece) -> Bool in
    piece.contains("NavigationLink")
}

整理第一层的数据

采用二维数组,

element[0] 第一个元素,文件夹初步编号

element[1] 第二个元素,内容

var i = 0
let cnt = rawInfo.count
// midData
// 0, content zero
// 1, content one
var midData = [[String]]()
while i < cnt{
    midData.append(["\(i)", rawInfo[i]])
    i += 1
}
第 4 步,整理第 2 层数据

总共就两层,就是整理里层的数据

先判断,包含 “Section”,就是存在第二层

不包含 “Section”,直接添加

// handledData
// 0_0, content zero zero
// 0_1, content zero one
// 1, content one
var handledData = [[String]]()
print("-------")

for piece in midData{
    
    if piece[1].contains(target.start){
        let list = extract(content: piece[1])
        // list.debug()
        let temp = list.enumerated().map({ (tmp) ->  [String] in
            ["\(piece[0])_\(tmp.offset)", tmp.element]
        })
        // temp.debug()
        handledData.append(contentsOf: temp)
        
    }
    else{
        
        handledData.append(piece)
    }
    
}
最后,完成文本解析,建立索引

还是二维数组,

element[0] 第 1 个元素,文件夹名称

element[1...] 剩余的元素,对应的类名列表

var result = [[String]]()
// index, file list


for piece in handledData{
    if let list = regex(with: piece[1]){
       // list.debug()
        let tmp = [piece[0]] + list
        result.append(tmp)
    }

}

还需要做的,根据类名找文件名,

建立文件夹,移动相应的文件进去

github repo

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值