In delimited string replace substring between the delimiters only if the substring matches replacement value

左心房为你撑大大i 提交于 2021-01-28 22:39:33

问题


I need to in a delimited string, replace substring between the delimiters only if the substring matches the replacement value

Using this in Google sheets

The matching

var ifind = ["AA", "CaaL"];
var ireplace = ["zz", "Bob"];

zz replaces AA
Bob replaces CaaL

I have

| Id | Segment            |
|----|--------------------|
| 1  | AAA AA|AA|CaaL AA  |
| 2  | AAA-AA|AA|CaaL     |
| 3  | AAA, AA|AA|AA      |
| 4  | AA                 |
| 5  | AA AA              |
| 6  | AA, AA             |
| 7  |                    |
| 8  | CaaL               |
| 9  | AA                 |

I need

| Id | Segment           |
|----|-------------------|
| 1  | AAA AA|zz|CaaL AA |
| 2  | AAA-AA|zz|Bob     |
| 3  | AAA, AA|zz|zz     |
| 4  | zz                |
| 5  | AA AA             |
| 6  | AA, AA            |
| 7  |                   |
| 8  | Bob               |
| 9  | zz                |

I have tried (amongst other things)

return [iFinds.reduce((str, k) => str.replace(new RegExp('\\b'+k+'\\b','g'),map[k]), input[0])];

and

 return [iFinds.reduce((str, k) => str.replace(new RegExp('(?![ .,]|^)?(\\b' + k + '\\b)(?=[., ]|$)','g'),map[k]), input[0])];

and

return [iFinds.reduce((str, k) => str.split(k).join (map[k]), input[0])];

My function (from here)

function findReplace_mod1() {
  const ss = SpreadsheetApp.getActiveSheet();
  const col = ss.getRange(2, 3, ss.getLastRow()).getValues();
  
  var ifind = ["AA", "Caal"];
  var ireplace = ["zz", "Bob"];
  
  var map = {};
  ifind.forEach(function(item, i) {
    map[item] = ireplace[i];
  });
  
  //const map = { Fellow: 'AAA', bob: 'BBB' };
  const iFinds = Object.keys(map);
  ss.getRange(2, 3, ss.getLastRow()).setValues(col.map(fr));

  function fr(input) {
    return [iFinds.reduce((str, k) => str.replace(k, map[k]), input[0])];
  }
}

Thanks


回答1:


Your fixed function can look like

function findReplace_mod1() {
  const ss = SpreadsheetApp.getActiveSheet();
  const col = ss.getRange(2, 3, ss.getLastRow()).getValues();
  var ifind = ["AA", "CaaL"];
  var ireplace = ["zz", "Bob"];
  
  var map = {};
  ifind.forEach(function(item, i) {
    map[item] = ireplace[i];
  });
  
  //const map = { Fellow: 'AAA', bob: 'BBB' };
  const regex = new RegExp("(?<![^|])(?:" + ifind.join("|") + ")(?![^|])", "g");
  ss.getRange(2, 3, ss.getLastRow()).setValues(col.map(fr));

  function fr(input) {
    return input.map(c => c.replace(regex, (x) => map[x]));
  }
}

The pattern will look like

/(?<![^|])(?:AA|CaaL)(?![^|])/g

where

  • (?<![^|]) - is a negative lookbehind that fails the match if there is a | or start of a string immediately to the left of the current location
  • (?:AA|CaaL) - a AA or CaaL
  • (?![^|]) - is a negative lookahead that fails the match if there is a | or end of a string immediately to the right of the current location.

See the regex demo online (negative lookarounds are replaced with positive ones since the demo is run against a single multiline string, not a set of separate strings).




回答2:


The string to replace

  • starts with | or start of the string ^
  • ends with | or end of the string $

The regex needs to be

str.replace(new Regexp(`(\\||^)${k}(\\||$)`), `$1${map[k]}$2`)

/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
function findReplace_mod2() {
  const col = [['AAA AA|AA|CaaL AA'], ['AA'], ['AAA-AA|AA|CaaL']];
  const map = { AA: 'zz', CaaL: 'Bob' };
  const iFinds = Object.keys(map);
  console.info(col.map(fr));

  function fr(input) {
    return [iFinds.reduce((str, k) => str.replace(new RegExp(`(\\||^)${k}(\\||$)`), `$1${map[k]}$2`), input[0])];
  }
}

findReplace_mod2();
<!-- https://meta.stackoverflow.com/a/375985/ -->    <script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>


来源:https://stackoverflow.com/questions/65063302/in-delimited-string-replace-substring-between-the-delimiters-only-if-the-substri

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!