Swift:正则表达式捕获数字的数学运算

时间:2014-10-04 16:20:43

标签: regex swift capture

我喜欢使用正则表达式将“我跑12英里”更改为“我跑24英里”。 “12”可以是任何数字。我使用函数“replace2()”来进行数学运算。传递给函数replace2(“$ 1”)的捕获参数“$ 1”很好。请帮忙!

func replace( str:String, pattern : String, repl:String)->String?{
    let regex = NSRegularExpression .regularExpressionWithPattern(pattern, options: nil,error: nil)
    let replacedString = regex.stringByReplacingMatchesInString( str, options: nil,
        range: NSMakeRange(0, countElements( str)), withTemplate: repl )
    return replacedString

}
replace( "I run 12 miles and walk 12.45 km","\\d+(.\\d+)?", "-")!

func replace2(x: String)->String {
    let xx = x.toInt()! * 2     // error : return nil?
    return String(format: "\(xx)")
}
replace( "I run 12 miles ","(\\d+)", replace2("$1") )!    // error

3 个答案:

答案 0 :(得分:0)

在操场上试试这个:

let str1: NSString = "I run 12 miles"
let str2 = "I run 12 miles"

let match = str1.rangeOfString("\\d+", options: .RegularExpressionSearch)
let finalStr = str1.substringWithRange(match).toInt()
let n: Double = 2.2*Double(finalStr!)

let newStr = str2.stringByReplacingOccurrencesOfString("\\d+", withString: "\(n)", options: NSStringCompareOptions.RegularExpressionSearch, range: nil)

println(newStr) //I run 26.4 miles


//or more simply
let newStr2 = "I run \(n) kilometers"
//yes, I know my conversion is off

答案 1 :(得分:0)

如果要动态捕获值并根据捕获的值替换它们,则必须使用enumerateMatchesInString。然后,您可以编写一个执行替换的循环:

func stringWithDoubleNumbers(string: String) -> String {
    // build array of ranges that need replacing

    var ranges = [NSRange]()
    let regex  = NSRegularExpression(pattern: "[\\d.]+", options: nil, error: nil) as NSRegularExpression
    regex.enumerateMatchesInString(string, options: nil, range: NSMakeRange(0, countElements(string))) {
        match, flags, stop in

        ranges.append(match.range)
    }

    var doubledString = NSMutableString(string: string)

    // iterate backwards so that location is valid despite other replacements

    for range in reverse(ranges) {
        let foundString = doubledString.substringWithRange(range)

        if let value = foundString.toInt() {
            let numericString = "\(value * 2)"
            doubledString.replaceCharactersInRange(range, withString: numericString)
        } else {
            let value = NSString(string: foundString).doubleValue
            let numericString = "\(value * 2.0)"
            doubledString.replaceCharactersInRange(range, withString: numericString)
        }
    }

    return doubledString
}

我做一些额外的逻辑来处理整数值而不是浮点类型,但是如果你不想担心这种复杂性,你可以简化这个。

答案 2 :(得分:0)

//我在上面用Steve和Rob代码进行实验,我想我可以得到代码来解决简单字符串的问题。我仍然遇到复杂字符串的问题。我尝试解析具有各种多个(-20)数字的数据记录,其中整数/双精度不是任何顺序,例如在单个例程中处理str2和str3。无论如何,谢谢Steve和Rob。

let str2 = "I run 89 miles and 28.576 km"
let str3 = "I run 89.45 miles and 34 km in 34F degree"

var re = NSRegularExpression(pattern: "(\\d+).* (\\d+\\.\\d+)", options: nil, error: nil)
var match = re.firstMatchInString(str2, options: nil, range: NSMakeRange(0, countElements(str2)))

var startIndex = advance(str2.startIndex, match.rangeAtIndex(1).location)
var endIndex   = advance(str2.startIndex, match.rangeAtIndex(1).location + match.rangeAtIndex(1).length)
let x1 = str2.substringWithRange(Range(start: startIndex, end: endIndex)).toInt()!

X1

startIndex = advance(str2.startIndex, match.rangeAtIndex(2).location)
endIndex   = advance(str2.startIndex, match.rangeAtIndex(2).location + match.rangeAtIndex(2).length)
let x2 = str2.substringWithRange(Range(start: startIndex, end: endIndex))
let x2x = NSString(string: x2).doubleValue
let n1 = x1 * 2
let n2: Double = 2.0 * x2x

str2.stringByReplacingOccurrencesOfString("(\\d+)(.* )(\\d+\\.\\d+)", withString: "\(n1)$2\(n2)", options: NSStringCompareOptions.RegularExpressionSearch, range: nil)

//我跑了178英里和57.152公里“