skip to Main Content

I have a json of the following format:

[
  {
    "MyField": "Hello World",
    "Year": 2020
  },
  {
    "MyField": "foo bar",
    "Year": 2020
  },
  {
    "MyField": "mystring1",
    "Year": 2020
  }
]

The value 2020 occurs 3 times above. In VS Code find/replace (ctrl + f), is there a way (perhaps using regex?) to only replace everything after a certain occurrence of a value, using the Replace All action? For example, I would like to replace everything after the 2nd occurrence of 2020 with 2021, while leaving the first occurrence intact.

Desired output:

[
  {
    "MyField": "Hello World",
    "Year": 2020
  },
  {
    "MyField": "foo bar",
    "Year": 2021
  },
  {
    "MyField": "mystring1",
    "Year": 2021
  }
]

2

Answers


  1. I see this extension: select-to-eof that makes what you want to do easy.

    1. Select the first occurrence you want included.
    2. Trigger the command select-to-eof: seed.
    3. All remaining matches are selected, you can type your replacement.

    select to end of file demo

    Login or Signup to reply.
  2. I don’t think you can search and replace with this kind of logic
    directly inside Visual Studio Code. Using a regular expression with
    a positive lookbehind would be a way to achieve it, but unfortunately
    this will only work if the lookbehind has a fixed length.

    But for your simple case, you can select the last part of your file and
    only search and replace in the selection:

    enter image description here

    On some regex engines, use could use a lookbehind

    In some JavaScript engines (the case in my Chrome), you are allowed
    to use a variable length lookbehind. A demo here:

    https://regex101.com/r/O1iOhc/1

    The idea is to search for "year": 2020 only if it is preceded by
    "year": 2020 and anything else.

    For elaborated search and replacements : program it!

    To do more sophisticated search and replacements, you’ll need to do
    a bit of programming. Typically, in JavaScript, you can use a
    callback function instead of a replacement string. This way, you
    can use a counter or do anything complicated for the replacement.

    Here, I captured the field name and the separator in a first capturing
    group and any year (digits) in a second capturing group. The callback
    function will receive the full match as the first argument and then
    the capturing groups as other arguments. My logic is to take the
    current year and increment it by one, but only for occurrences
    higher than 1. Of course, the mathematical operation of year
    increment is just here as an example, to show you what it can bring
    compared to an IDE.

    const json = `[
      {
        "MyField": "Hello World",
        "Year": 2020
      },
      {
        "MyField": "foo bar",
        "Year": 2020
      },
      {
        "MyField": "mystring1",
        "Year": 2020
      }
    ]
    `;
    
    // Regular expression with a capturing group for the field name, some
    // optional spaces, the double-point and a second capturing group for
    // the numeric value.
    const regex = /(?<name>"Year"s*:s*)(?<value>d+)/g;
    
    let occurrence = 1;
    
    // Use a callback function for the replacement value so that we
    // can do some more elaborated logic.
    const result = json.replace(regex, (fullMatch, name, value) => {
      if (occurrence++ > 1) {
        let year = parseInt(value);
        return name + (String)(year + 1);
      } else {
        return fullMatch;
      }
    });
    
    console.log(result);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search