skip to Main Content

I have something like:

Some MY_WORD stupid txt='other text MY_WORD' and another MY_WORD  stupid text and txt='something else MY_WORD' and also txt='here nothing to replace' and here txt='again to replace MY_WORD here'

I want to replace MY_WORD with OTHER_WORD but only if it is inside txt=' and '

/(?<=txt='.*)MY_WORD(?=.*')/g


Some MY_WORD stupid txt='other text OTHER_WORD' and another MY_WORD  stupid text and txt='something else OTHER_WORD' and also txt='here nothing to replace' and hexe txt='again to replace OTHER_WORD here'

But look behind is not supported in all browsers, so it is not good approach.

A tried with this but even it says there are groups of matches, I $3 is empty.

(txt=')((.*)(MY_WORD))?

2

Answers


  1. You can match the text between txt=' and ' using a simple txt='[^']*' regex. Then, upon finding the matches, replace all occurrences of MY_WORD with what you need inside an arrow function:

    text.replace(/txt='[^']*'/g, (x) => x.replace(/MY_WORD/g, 'NEW_WORD'))
    

    where x stands for the whole match.

    See the JavaScript demo:

    var text = "Some MY_WORD stupid txt='other text MY_WORD' and another MY_WORD  stupid text and txt='something else MY_WORD' and also txt='here nothing to replace' and here txt='again to replace MY_WORD here'";
    console.log( text.replace(/txt='[^']*'/g, (x) => x.replace(/MY_WORD/g, 'NEW_WORD')) );
    Login or Signup to reply.
  2. I would just search for txt = '...MY_WORD and replace it with the help
    of a capturing group before MY_WORD. Also, handle optional spaces around
    the equal sign and be sure that MY_WORD is a full word and not part of
    a word (such as DUMMY_WORD) by also matching word boundaries with b.

    The regex pattern:

    /(txts*=s*'[^']*)bMY_WORDb/g
    

    I use [^']* instead of .*.

    Full JS working example where you can change the input to test it:

    const regex = /(txts*=s*'[^']*)bMY_WORDb/g;
    const replacement = `$1OTHER_WORD`;
    
    /**
     * This function is used to call a specific function callback only once
     * at the time. This is to avoid multiple events such as 'input' to run
     * multiple times and lead to a non-responding browser.
     *
     * @param {function} callback The function to call.
     */
    function onlyOnceAtATime(callback) {
      // Keep track of all the running callbacks.
      let runningCallbacks = new Map();
    
      return function (...args) {
        if (runningCallbacks.has(callback.name)) {
          return;
        }
    
        runningCallbacks.set(callback.name, true);
        callback(...args);
        runningCallbacks.delete(callback.name);
      };
    }
    
    // When the document is ready, attach the event handlers.
    document.addEventListener("DOMContentLoaded", function () {
      const input = document.getElementById("input");
      const output = document.getElementById("output");
    
      function updateOutput() {
        output.value = input.value.replace(regex, replacement);
      }
      
      // Each change in the input textarea should update the output textarea.
      input.addEventListener('input', onlyOnceAtATime(updateOutput));
      
      // When clicking in the output textarea, select all the text.
      output.addEventListener('click', (event) => {
        const target = event.target;
        target.setSelectionRange(0, target.value.length);
      });
      
      // For the first load, calculate the output.
      updateOutput();
    });
    .form-element {
      margin: 1em 0;
      display: flex;
      flex-direction: column;
    }
    
    label {
      padding-bottom: .2em;
      
      &::after {
        content: " :";
      }
    }
    
    textarea[readonly] {
      background: silver;
    }
    <form action="#">
      <div class="form-element">
        <label for="input">Input</label>
        <textarea name="input" id="input" cols="80" rows="5">Some MY_WORD stupid txt='other text MY_WORD' and another MY_WORD  stupid text and txt='something else MY_WORD' and also txt='here nothing to replace' and here txt='again to replace MY_WORD here'</textarea>
      </div>
      <div class="form-element">
        <label for="output">Output with <code>MY_WORD</code> replaced by <code>OTHER_WORD</code></label>
        <textarea name="output" id="output" cols="80" rows="5" readonly></textarea>
      </div>
    </form>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search