Search code examples
iosswiftstringcamelcasing

how can I edit lots of swift string at once?


In my project, I have Localizable.string file which is having more than 10,000 lines keyValue format. I need to convert all of keys which are dotCase format like "contentsList.sort.viewCount" to lowerCamelCase. how can I convert by using swift scripting? thank you.

as-is

"contentsList.horizontal.more" = "totall";

to-be

"contentsListHorizontalMore" = "totall";

Solution

  • First get all lines from your string. CompactMap your lines breaking it up into two components separated by the equal sign. Get the first component otherwise return nil. Get all ranges of the regex (\w)\.(\w). Replace the match range by the first + second group capitalized. This will remove the period. Return a collection of one element (snake case) + the other components joined by the separator equal sign. Now that you have all lines you just need to join them by the new line character:


    let string = """
    "contentsList.horizontal.more" = "totall";
    
    "whatever.vertical.less" = "summ";
    """
    

    let pattern = #"(\w)\.(\w)"#
    let lines = string.split(omittingEmptySubsequences: false,
                             whereSeparator: \.isNewline)
    let result: [String] = lines.compactMap {
        let comps = $0.components(separatedBy: " = ")
        guard var first = comps.first else { return nil }
        let regex = try! NSRegularExpression(pattern: pattern)
        let matches = regex.matches(in: first, range: NSRange(first.startIndex..., in: first))
        let allRanges: [[Range<String.Index>]] = matches.map { match in
            (0..<match.numberOfRanges).compactMap { (index: Int) -> Range<String.Index>? in
                Range(match.range(at: index), in: first)
            }
        }
        for ranges in allRanges.reversed() {
            first.replaceSubrange(ranges[0], with: first[ranges[1]] + first[ranges[2]].uppercased())
        }
        return (CollectionOfOne(first) + comps.dropFirst())
            .joined(separator: " = ")
    }
    let finalString = result.joined(separator: "\n")
    print(finalString)
    

    This will print

    "contentsListHorizontalMore" = "totall";

    "whateverVerticalLess" = "summ";