我如何运行替换函数一次?

How I run the replace function one time?

我只想 replaceFunction 到 运行 一次。现在只有第一次才能正常工作,E-1 return Ε-1 (APPLE) 但是当用户尝试再次编辑文本字段时系统检测到 ε-1 和 return Ε-1 (APPLE) (APPLE)..

td.onchange = function(e) {
    this.value = this.value.replace(/(\E-(\d+))/g, replaceFunction);

    function replaceFunction(match) {
        // add additional rules here for more cases
        if (match === "E-1") return "Ε-1 (APPLE)";
        if (match === "E-2") return "Ε-2 (SUMSUNG)";
        .
        .
        .
        if(match === "E-99") return "Ε-99 (LG)";
        return match;
    }
}

我如何阻止它?

您还可以使用类似这样的条件:

if (match === "E-1" && match !== "Ε-1 (APPLE)") return "Ε-1 (APPLE)";

这可以优化,如果你把映射放到对象中:

var map = {
    "E-1": "Ε-1 (APPLE)",
    ...
}

if (map[match] && !map[match] !== match) { return map[match]; }

为此,您需要正则表达式,该正则表达式也匹配方括号中的单词:

var names = ['APPLE', 'SAMSUNG'];

var re = new RegExp('(E-(\d+))(?! \((?:' + names.join('|') + ')\))', 'g');

另一种解决方案是仅使用数组(这仅在 E-NUM 匹配数组中的索引时有效)

var names = ['APPLE', 'SAMSUNG'];
var re = new RegExp('(E-(\d+))(?! \((?:' + names.join('|') + ')\))', 'g');
// regex explanation, same as yours but \d is because it's a string
// we create negative look ahead so we check if next text
// after E-1 is not " (" and any of the names.
// we use (?: to group what's inside it's the same as with ()
// but the value will not be captured so there will be
// no param in function for this group
// so this regex will be the same as yours but will not match "E-1 (APPLE)"
// only "E-1"

this.value = this.value.replace(re, replaceFunction);

function replaceFunction(match, eg, num) {
   // convert string to number E starts 
   var i = parseInt(num, 10) - 1;
   if (i <= names.length) {
     return match + ' (' + names[i] + ')';
   }
}

正则表达式和函数可以在更改函数之外创建,因此它不会在每次更改时创建新函数。

替换时,还可以选择先行查找 space 和后面的括号。这样,在 replacer 函数中,您可以检查后面是否 已经是 您想要的值(例如 (APPLE))。如果是,则什么都不做 - 否则,替换为新字符串:

const replacementsE = [
  , // nothing for E-0
  'APPLE',
  'SUMSUNG',
];

td.onchange = function(e) {
  td.value = td.value.replace(/E-(\d+)(?= \(([^)]+)\)|)/g, replaceFunction);

  function replaceFunction(match, digits, followingString) {
    const replacement = replacementsE[digits];
    if (!replacement || replacement === followingString) {
      return match;
    }
    return `E-${digits} (${replacement})`;
  }
}
<input id="td">

/E-(\d+)(?= \(([^)]+)\)|)/ 所做的是:

  • E- - 匹配 E-
  • (\d+) - 捕获组中的数字
  • (?= \(([^)]+)\)|) 向前看:
    • \(([^)]+)\) 文字 (,后跟非 ) 字符,再后跟 )。如果匹配,非)字符将是第二个捕获组
    • | - 或匹配空字符串(以便前瞻有效)

数字将是第一个捕获组;回调中的 digits 变量。非)字符将是第二个捕获组;回调中的 followingString 变量。

如果您还想允许删除最后的 ),则将最后的 ) 设为可选,并确保字符集不匹配 spaces (因此 APPLE 之后的 space,没有结尾 ),不会匹配):

const replacementsE = [
  , // nothing for E-0
  'APPLE',
  'SUMSUNG',
];

td.onchange = function(e) {
  td.value = td.value.replace(/E-(\d+)(?= \(([^) ]+)\)?|)/g, replaceFunction);

  function replaceFunction(match, digits, followingString) {
    const replacement = replacementsE[digits];
    if (!replacement || replacement === followingString) {
      return match;
    }
    console.log(followingString)
    return `E-${digits} (${replacement})`;
  }
}
<input id="td">

如果要允许任意个字符在最后)之前被删除,那么检查是否替换startsWith以下字符串:

const replacementsE = [
  , // nothing for E-0
  'APPLE',
  'SUMSUNG',
];

td.onchange = function(e) {
  td.value = td.value.replace(/E-(\d+)(?= \(([^) ]+)\)?|)/g, replaceFunction);

  function replaceFunction(match, digits, followingString, possibleTrailingParentheses) {
    const replacement = replacementsE[digits];
    if (!replacement || replacement === followingString || replacement.startsWith(followingString)) {
      return match;
    }
    
    return `E-${digits} (${replacement})`;
  }
}
<input id="td">