Javascript Regexp - replace函数应决定不替换匹配的字符串,让其他带括号的子匹配字符串与匹配一起工作

时间:2014-06-11 04:45:01

标签: javascript regex string

这是一个相当简单的例子,我想要的是:如果replace函数决定不替换'匹配' - 每个其他带括号的子匹配字符串:'(“。+?”:)'或'([^ \ s ] +?:)'也应该对这个匹配起作用而不是仅仅因为第一个子匹配字符串匹配而跳过它。

简单的例子,请看一下:

var fieldNames = [
    { displayName: "Sender", systemName: "from_field"},
    { displayName: "Receiver(addressee)", systemName: "to_field"},
    { displayName: "Author", systemName: "author_id_field"}
];

var query = 'AND (ENTITY(Company),OR(Sender:john, Receiver(addressee):john),OR(#"Receiver(addressee)":Tanaka),OR(#"Abracadabra":Phil)) OR Author:Stan';

// What I want to retrieve as a result:
// 'AND (ENTITY(Company),OR(from_field:john, to_field:john),OR(to_field:Tanaka),OR(#"Abracadabra":Phil)) OR author_id_field:Stan'

// I want to:
// Replace '#"displayName":' with 'systemName:'
// Replace '"displayName":' with 'systemName:'
// Replace 'displayName:' with 'systemName:'
regexp = /(#".+?":)|(".+?":)|([^\s]+?:)/gi;

var newQuery = query.replace(regexp, replaceDisplayName);
console.log('Result:');
console.log(newQuery);

function replaceDisplayName(match, p1, p2, p3) {
    console.log("match: " + match);
    var potentialDisplayName;
    if (p1) {
        // Get the word(s) inside: '#"displayName":' -> get 'displayName'
        potentialDisplayName = match.substring(2, match.length - 2);
    } else if (p2) {
        // Get the word(s) inside: '"displayName":' -> get 'displayName'
        potentialDisplayName = match.substring(1, match.length - 2);
    } else if (p3) {
        // Get the word(s) inside: 'displayName:' -> get 'displayName'
        potentialDisplayName = match.substring(0, match.length - 1);
    }

    console.log('potentialDisplayName: ' + potentialDisplayName);
    var systemName = getFieldNameByDisplayName(potentialDisplayName);
    console.log('found systemName: ' + systemName);

    var newStringValue = systemName ? systemName + ":" : match;
    return newStringValue;
};

function getSystemNameByDisplayName(displayName) {

    for (var i = 0; i < fieldNames.length; i++) {
        if (fieldNames[i].displayName.toLowerCase() === displayName.toLowerCase()) {
            return fieldNames[i].systemName;
        }
    }

    return null;
};

结果:

  

'AND(ENTITY(公司),或(发件人:约翰,   to_field:约翰),OR(# “接收机(收件人)”:田中),OR(# “胡言乱语”:菲尔))   或author_id_field:Stan'

我想要的结果:

  

'AND(ENTITY(公司),或(from_field:john,   to_field:john),OR(to_field:Tanaka),OR(#“Abracadabra”:Phil))或   author_id_field:斯坦'

问题是,例如第一场比赛将是: '(实体(公司),OR(发件人:' 此值不是'displayName',因此不会找到systemName,我将无法替换。但我想'发件人:'仍然被'to_field'取代。但是,这整个匹配将被跳过,因为第一个子匹配字符串'(#“。+?”:)'已经使用它,所以它没有给出其他子匹配字符串的机会:'(“。+?”: )'和'([^ \ s] +?:)'使用它。

感谢您的时间,感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

试一试。我确实构建了从displayNamesystemName的快速查找以使用:

var fieldNames = [
        { displayName: "Sender", systemName: "from_field"},
        { displayName: "Receiver(addressee)", systemName: "to_field"},
        { displayName: "Author", systemName: "author_id_field"}
    ],
    regex = /(?:#?"?)([^":]+)(?:"?):/i,
    map = {
        "Sender": "from_field",
        "Receiver(addressee)": "to_field",
        "Author": "author_id_field"
    };

var test = [
    '#"Sender":',
    '"Sender":',
    'Sender:',
    '#"Receiver(addressee)":',
    '"Receiver(addressee)":',
    'Receiver(addressee):',
    '#"Unknown":'
];

for (var i=0; i<test.length; i++) {
    var systemName = test[i].replace(regex, function(match, p1) {
       if (p1) return map[p1] || p1;
    });
    console.log("Display[%s] = System[%s]", test[i], systemName);
}
// output:
// Display[#"Sender":] = System[from_field] 
// Display["Sender":] = System[from_field] 
// Display[Sender:] = System[from_field] 
// Display[#"Receiver(addressee)":] = System[to_field] 
// Display["Receiver(addressee)":] = System[to_field] 
// Display[Receiver(addressee):] = System[to_field]
// Display[#"Unknown":] = System[Unknown] 

如果匹配的displayname未知(_i.e。在查找地图中),则只是按原样返回。