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

Regex Swift:正则表达式捕获数的数学运算,regex,swift,capture,Regex,Swift,Capture,我喜欢用正则表达式将“我跑12英里”改为“我跑24英里”。“12”可以是任何数字。我使用函数“replace2()”进行数学运算。传递给函数replace2(“$1”)的捕获参数“$1”没有问题。请帮忙 func replace( str:String, pattern : String, repl:String)->String?{ let regex = NSRegularExpression .regularExpressionWithPattern(pattern, opt

我喜欢用正则表达式将“我跑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

在操场上试试这个:

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

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

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
}

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

//我用上面的Steve和Rob代码进行了实验,我想我可以得到代码来解决简单字符串的问题。我仍然有复杂字符串的问题。我试着解析一个数据记录,它包含多个(-20)数字,或者是整数或者是双精度数字,而不是像在一个例程中处理str2和str3那样的任何序列。不管怎样,多亏了史蒂夫和罗伯

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


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

谢谢。这很有效。但我尝试乘以许多(未知)数字,如“我在-34F度下跑了34英里10.54公里。”我喜欢将所有3个数字乘以2。非常感谢。这很有效。但我试着使用纯Swift并试图避开“NS”“除了多余的东西外,还要尽可能多的东西。你能将字符串“我在-34F度下跑34英里和10.54公里”中的所有数字加倍为“我在-68F度下跑68英里和21.08公里”吗。在Perl中,它很简单:“s/(\d+(\。\d+)/$1*2/ge”,如果您愿意,我可以执行swift函数。再长一点,好极了!非常感谢。
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)