2010-05-22 60 views
7

考慮此javascript:的Javascript正則表達式來點符號轉換爲括號標記

var values = { 
    name: "Joe Smith", 
    location: { 
     city: "Los Angeles", 
     state: "California" 
    } 
} 

var string = "{name} is currently in {location.city}, {location.state}"; 

var out = string.replace(/{([\w\.]+)}/g, function(wholematch,firstmatch) { 
    return typeof values[firstmatch] !== 'undefined' ? 
     values[firstmatch] : wholematch; 
}); 

這將輸出如下:

Joe Smith is currently in {location.city}, {location.state} 

但我想輸出如下:

Joe Smith is currently in Los Angeles, California 

我正在尋找一種很好的方法來將在字符串中的大括號之間找到的點符號的多個級別轉換爲多個參數用括號來使用,就像這樣:

values[first][second][third][etc] 

從本質上講,在這個例子中,我試圖找出正則表達式的字符串和功能,我需要有相當於落得:

out = values[name] + " is currently in " + values["location"]["city"] + 
    values["location"]["state"]; 

注意:我想這樣做,而不使用eval()

+0

剛注意到一個錯字。將'var joe'重命名爲'var values' – Tauren 2010-05-22 05:17:17

+0

另一個類似的問題有@ J-P替代解決方案來解答這裏的答案。它看起來相當優雅:http://stackoverflow.com/questions/3344392/dynamic-deep-selection-for-a-javascript-object/3344487#3344487 – Tauren 2010-07-28 00:28:15

回答

10

使用輔助函數來迭代地訪問屬性:

function getNestedValue(obj, prop) { 
    var value, props = prop.split('.'); // split property names 

    for (var i = 0; i < props.length; i++) { 
    if (typeof obj != "undefined") { 
     obj = obj[props[i]]; // go next level 
    } 
    } 
    return obj; 
} 

var string = "{name} is currently in {location.city}, {location.state}"; 

var out = string.replace(/{([^}]+)}/g, function(wholematch,firstmatch) { 
    var value = getNestedValue(joe, firstmatch); 
    return typeof value !== 'undefined' ? value : wholematch; 
}); 
// "Joe Smith is currently in Los Angeles, California" 

嘗試上述例子here

編輯:一些輕微優雅,使用Array.prototype.reduce方法,新的ECMAScript第五版標準的一部分:

function replace(str, obj) { 
    return str.replace(/{([^}]+)}/g, function(wholematch,firstmatch) { 
    var value = firstmatch.split('.').reduce(function (a, b) { 
     return a[b]; 
    }, obj); 
    return typeof value !== 'undefined' ? value : wholematch; 
    }); 
} 

replace("{name} is currently in {location.city}, {location.state}", values); 
// "Joe Smith is currently in Los Angeles, California" 

嘗試新的例子here

+0

@CMS:很好,工作!然而,它並不像基於正則表達式的解決方案那麼優雅,我想相信有一種正則表達方式可以做到這一點。然後,再次,也許這是浪費時間尋求正則表達式的解決方案。 – Tauren 2010-05-22 05:14:47

+0

@CMS:你的正則表達式不允許大括號之間的任何東西?如果我想限制數值爲有效的javascript變量名'[a-zA-Z0-9 _ \。]',是不是最好使用'/ {([\ w \。] +)}/g'?實際上,這會在開始時允許一段時間,這是不允許的,但它很接近。哦,是的,我想我還需要包含'$'。 – Tauren 2010-05-22 05:25:47

+0

@Tauren,對它有點寬容,我不在乎太多,因爲當你用括號表示法(或在對象字面量中使用字符串)訪問屬性時,沒有任何限制,例如'obj [「3.xx \ u0009「]'... – CMS 2010-05-22 06:18:06

0

我不知道如何將這種在Javascript整合,但這裏是一個使用正則表達式做你需要的轉化的Java代碼片段:

String[] tests = { 
     "{name}", 
     "{location.city}", 
     "{location.state.zip.bleh}", 
    }; 
    for (String test : tests) { 
     System.out.println(test.replaceAll("\\{?(\\w+).?", "[$1]")); 
    } 

此打印:

[name] 
[location][city] 
[location][state][zip][bleh] 

本質上,它將所有出現的\{?(\w+).?替換爲[$1]

+0

嗯,有趣。但是,即使我在JS中得到了這個工作,我想我最終會得到一個我需要'eval'的字符串,這是我想避免的。 – Tauren 2010-05-22 07:39:44

0

你可以看看發表在comp.lang.javascript上的Error-free deep property access?這個主題 - 這裏提供了幾種做你想做的事情的方法。

對於正則表達式,您需要的全部是/{.*?}/g