How to check if the text can be spinned using regex?

I am trying to spin text using a regular expression. I am trying to make it work for Googles Apps Script. I have tried the expression (\{[^\}]+\}|[^\{\}]*), but it fails in many cases. I just want it to In case you don't know what I mean by spinning text, it's explained below:

{This|That} is a {cat|dog} gives

This is a cat This is a dog That is a cat That is a dog

Answers:

Answer

I would not use a regular expression for this, I would just implement a state machine.

You just keep track of what level you're on. This is rudimentary, and can be expanded to work recursively if needed.

See also

/** Can also be written as:
 *
 * const isValid=s=>s.split('').reduce((r,c)=>c==='{'?r+1:(c==='}'?r-1:r),0)===0;
 */
function isValid(str) {
  var state = 0;
  for (let i = 0; i < str.length; i++) {
    switch (str.charAt(i)) {
      case '{': state++; break;
      case '}': state--; break;
    }
  }
  return state === 0;
};
.as-console-wrapper { top: 0; max-height: 100% !important; }

A safer alternative

A better approach would be to work inside-out. Just get the LAST index of an opening brace, and check to see if it has a closing brace (and pipe) after it, but before the next opening brace.

function isValid(str, strict) {
  var maxAttempts = 100; // Do not let this loop too many times...
  while (str.lastIndexOf('{') < str.indexOf('}', str.lastIndexOf('{'))) {
    let start = str.lastIndexOf('{');
    let nextStart = str.indexOf('{', start + 1); // Check ahead (optional)
    let mid = str.indexOf('|', start); // If you need a pipe check...
    let end = str.indexOf('}', start);
    //console.log(JSON.stringify({ str : str, start : start, mid : mid, end : end}));
    let isValid = start > -1 && end > -1 && (nextStart === -1 || nextStart > end);
    if (strict === true && (mid < start || mid > end)) {
      return false; // If pipes are required, check for their existence.
    }
    if (isValid) {
      str = str.substring(0, start) + str.substr(end + 1);
    }
    // Safeguard for accidental infinite recursion...
    if (maxAttempts-- < 0) { throw Error('Inifinite recursion detected!'); }
  }
  return str.indexOf('{') === -1 || str.indexOf('}') === -1;
}

/* Valid   */ console.log(isValid('{|}'));
/* Valid   */ console.log(isValid('{|}', true));
/* Invalid */ console.log(isValid('{}', true));
/* Invalid */ console.log(isValid('}{'));
/* Invalid */ console.log(isValid('{}}{{}'));
.as-console-wrapper { top: 0; max-height: 100% !important; }

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.