-1

I'm looking for a pattern that match with

    "changes": [
      "5.12.0",
      "5.14.0"
    ],
...
    "changes": [
      "1",
      "5.0.0",
      "5.10.1"
    ],
...
    "changes": [
      "4.4",
      "5.0.0",
      "5.10.1"
    ],

I'm no expert, I've tried maybe 40 or 50 different solutions, here's my last try:

/"changes": \[\s*("([0-9](.+))*"(,+))*\s*\],/

i try this one and it works, ty.

"changes": \[\s*("([0-9](.+))*"(,+)\s )+("([0-9](.+))*"\s)\],
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Shoooryuken
  • 242
  • 2
  • 14
  • How about reading the file, parsing the retrieved json into an object, iterating the object and deleting each `changes` entry where the value is an array; after that `JSON.stringify` the object and writing the json to the file? – Peter Seliger Aug 07 '23 at 08:07

3 Answers3

1

I would do it in two steps:

  1. Search for the list of versions between the brackets after "changes":

    /"changes":\s*\[\s*([^\]]+)\s*\]/g : https://regex101.com/r/XHaxJ0/4

  2. For each match, you'll get the list of versions in the capturing group 1:

    "4.4",
          "5.0.0",
          "5.10.1"
    

    You can then extract each version with /[\d.]+/g : https://regex101.com/r/XHaxJ0/2

The Javascript code:

const input = `    "changes": [
      "5.12.0",
      "5.14.0"
    ],
...
    "changes": [
      "1",
      "5.0.0",
      "5.10.1"
    ],
...
    "changes": [
      "4.4",
      "5.0.0",
      "5.10.1"
    ],`;

const regexChangesContent = /"changes":\s*\[\s*([^\]]+)\s*\]/g;
const regexVersion = /[\d.]+/g;

// To fill with the found versions in the changes arrays.
let versions = [];

let matchChangesContent,
    matchVersion;

while ((matchChangesContent = regexChangesContent.exec(input)) !== null) {
  while ((matchVersion = regexVersion.exec(matchChangesContent[1])) != null) {
    versions.push(matchVersion[0]);
  }
}

console.log(versions);

EDIT since question has changed

As you just want to delete the "changes" entries, I would do the following:

const input = `    "changes": [
      "5.12.0",
      "5.14.0"
    ],
    "date": "01.01.2023",
    "changes": [
      "1",
      "5.0.0",
      "5.10.1"
    ],
    "property": "value",
    "should_stay": true,
    "changes": [
      "4.4",
      "5.0.0",
      "5.10.1"
    ],`;

const regexChanges = /"changes":\s*\[\s*[^\]]+\s*\]\s*,/g;

console.log(input.replace(regexChanges, ''));
Patrick Janser
  • 3,318
  • 1
  • 16
  • 18
0

sorry if i dont clarify, i have a json with 3 000k lines, with a big array of object and i want to delete all changes versions of any object.

the solution is :

"changes": \[\s*("([0-9](.+))*"(,+)\s*)+("([0-9](.+))*"\s*)\],

thank you ! i spend 4 hours this morning and i found some minutes after asking :(

Shoooryuken
  • 242
  • 2
  • 14
  • Effectively, it's always best to put the main intention in the question. My answer therefore is just giving you what I thought you were trying to do. – Patrick Janser Aug 04 '23 at 12:59
  • sorry and thank you for your times. – Shoooryuken Aug 04 '23 at 13:04
  • In case the JSON is too long and the regex search breaks because the string is too big, then you could parse it with [JSON.parse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse) and then [remove all the properties which are called "changes" recursively](https://stackoverflow.com/a/31729267/653182) (replace `$meta` by `changes`). – Patrick Janser Aug 04 '23 at 13:09
  • 1
    If you know that `"changes": [ ... ],` can't be something else in the JSON then you could simplify your regex to `/"changes":\s*\[\s*[^\]]+\]\s*,/gs` (demo here: https://regex101.com/r/XHaxJ0/3) as it will probably run faster without checking all the strings, digits, dots and commas. If you want to keep the precise pattern, then you can replace your capturing groups `( ... )` by non-capturing groups `(?: ... )` to save time and memory. – Patrick Janser Aug 04 '23 at 13:15
  • 1
    **CAUTION** : your regex pattern doesn't seem to work correctly! It's "eating" some other properties in the JSON :-/ See it in action here: https://regex101.com/r/zg1PEz/1 – Patrick Janser Aug 04 '23 at 13:21
0

From my above comment ...

"How about reading the file, parsing the retrieved json into an object, iterating the object [recursively] and deleting each changes entry where the value is an array; after that JSON.stringify the object and writing the json to the file?"

// const import fs from 'fs';

function deleteEveryChangesArrayRecursively(data) {
  if (Array.isArray(data)) {

    data.forEach(item => deleteEveryChangesArrayRecursively(item));

  } else if (data && typeof data === 'object') {
    Object
      .entries(data)
      .forEach(([key, value]) => {
        if (key === 'changes' && Array.isArray(value)) {

          Reflect.deleteProperty(data, key);
        } else {
          deleteEveryChangesArrayRecursively(value);
        }
      });
  }
  return data;
}

/*function getDataFromJsonFile(path) {
  try {
    const json = fs
      .readFileSync(path, { encoding: 'utf8' });

    return { success: true, data: JSON.parse(json) };
  } catch (exception) {
    return { success: false, exception };
  }
}
function writeDataAsJsonFile(path, data) {
  try {
    fs.writeFileSync(path, JSON.stringify(data));

    return { success: true };
  } catch (exception) {
    return { success: false, exception };
  }
}*/

// mocking both, read and parse from file and stringify and write as file.
const getDataFromJsonFile = () => ({ data: structuredClone(mockData) });
const writeDataAsJsonFile = () => ({ success: true });

let { data = null, success, exception }
  = getDataFromJsonFile('./data.json');

if (data !== null) {
  ({ success, exception } = writeDataAsJsonFile(
    './data.json',
    deleteEveryChangesArrayRecursively(data),
  ));
}
console.log({ mockData, data, success, exception });
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
  // mocking the parsed json.
  const mockData = {
    foo: [{
      changes: [0, 1, 2],
    }, {
      foobar: ['FOO', 'BAR'],
      changes: 'not an array',
    }, {
      foobaz: 'FOO BAZ',
      changes: [3, 4, 5],
    }, {
      foobiz: [{
        foobizbar: ['FOO', 'BIZ', 'BAR'],
        changes: 'not an array',
      }, {
        foobizbaz: 'FOO BIZ BAZ',
        changes: [6, 7, 8],
      }, {
        foobizbiz: 'FOO BIZ BIZ',
        changes: [9, 0, 1],
      }],
    }, {
      changes: [2, 3, 4],
    }, {
      foobar2: ['FOO', 'BAR', '2'],
      changes: 'not an array',
    }, {
      foobaz2: 'FOO BAZ 2',
      changes: [5, 6, 7],
    }, {
      foobiz2: [{
        foobiz2bar: ['FOO', 'BIZ', '2', 'BAR'],
        changes: 'not an array',
      }, {
        foobiz2baz: 'FOO BIZ 2 BAZ',
        changes: [8, 9, 0],
      }, {
        foobiz2biz: 'FOO BIZ 2 BIZ',
        changes: [1, 2, 3],
      }],
    }],
  };
</script>
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37