#javascript #node.js #regex
#javascript #node.js #регулярное выражение
Вопрос:
Мне нужно определить шаблоны, подобные приведенным ниже, внутри очень большой строки и заменить их на «null»:
["pmeta", ["ImageSelectStoreFront", null, 3, 4, 2, null, "Storefront", []]],
["pmeta", ["/m/01pns0", null, 3, 3, 3, null, "fire hydrant", []], null, [1]],
["pmeta", ["/m/0199g", null, 3, 3, 3, null, "bicycle", []], null, [1]],
Эти строки выглядят как JSON, но строка, в которой они отображаются, не является JSON, поэтому нет смысла ее разбирать. Мне также не нужно анализировать этот JSON, мне нужно удалить его из строки, в которой он появляется.
Единственные части, которые всегда одинаковы, — это ["pmeta",
и закрывающая скобка и запятая в конце.
Я изучаю регулярное выражение как возможное решение, но я совершенно новичок в этом и не придумал ничего, близкого к полезному.
Кто-нибудь может дать мне несколько указателей на регулярные выражения или предложить другие способы достижения этого?
Комментарии:
1. Вместо этого проанализируйте JSON
2. Неясно, что вы хотите заменить
3. @CertainPerformance Это на самом деле не было бы полезно для меня. Этот JSON отображается в строке, и мне нужно избавиться от него, а не анализировать его.
4. @adiga Мне нужно заменить любую строку, которая начинается с
["pmeta",
и заканчивается последней, закрывающей скобкой, и все, что находится между ними.5. Выполните синтаксический анализ JSON -> filter -> serialise в JSON, это должно быть намного проще. Регулярное выражение будет очень неудобно писать и поддерживать. Пользовательский анализатор был бы проще для сравнения, но все равно требует намного больше работы, чем тривиальный синтаксический анализ -> фильтр -> сериализация.
Ответ №1:
Вместо регулярного выражения вы могли бы выполнить пользовательский синтаксический анализ. Это работает следующим образом:
- Найдите, есть ли во входных данных что-либо, начинающееся с
["pmeta"
. - Считайте, что
startIndex
- Найдите индекс последней закрывающей скобки после этого индекса, сохранив стопку скобок. Вы добавляете по одному элементу в стек для каждой открытой скобки, удаляете элемент для любой закрывающей скобки. Когда вы очищаете стек, это последняя закрывающая скобка. Считайте это как
endIndex
- Найдите раздел строки от
startIndex
доendIndex
и затем замените его наnull
.
Я сократил (и обезличил) ваш образец, заменив длинные значения на отдельные слова:
let input = `)]}'
["rresp",
"one",
null,
120,
["pmeta",["/m/01pns0",null,3,3,3,null,"fire hydrant",[]
]
,null,[1]
]
,"dynamic",null,["bgdata","two","","three"]
,"four","five"]`
let output = clean(input);
console.log("output", output);
function clean(text) {
let startIndex = text.indexOf('["pmeta"');
//nothing to remove - early exit
if (startIndex === -1) return text;
let endIndex = findLastOpenBracket(text, startIndex);
let toReplace = text.substring(startIndex, endIndex);
console.log("found text to replace:", toReplace);
return text.replace(toReplace, "null")
}
function findLastOpenBracket(text, startIndex) {
let openBrackets = [];
for (let i = startIndex; i < text.length; i ) {
let char = text[i];
if (char === "[") {
openBrackets.push(char);
} else if (char === "]") {
openBrackets.pop()
if(openBrackets.length === 0){
return i 1
}
}
}
}
Это предполагает, что будет закрывающая скобка, которая завершает последовательность. По общему признанию, findLastOpenBracket
функцию можно значительно улучшить, но я не знаю требований здесь, и она соответствует образцу данных. По крайней мере, это единый алгоритм, который можно заменить, остальные шаги остаются неизменными.
Еще одно замечание: шаг 4. немного громоздок. К сожалению, в JavaScript нет .splice
метода для строк, поэтому вам придется пойти длинным путем — получить подстроку -> заменить подстроку в строке. Вы можете вместо этого использовать Array.splice()
метод, если это необходимо, но я также нахожу его громоздким:
let text = "one,two,three";
//replace "two"
let startIndex = 4;
let endIndex = 7;
let arr = text.split("");
arr.splice(
startIndex,
endIndex - startIndex,
"null"
)
let output = arr.join("");
console.log(output);
Комментарии:
1. Большое спасибо за вашу помощь, я рассмотрю это решение завтра — уже очень поздно 🙂
2. Некоторые последующие мысли — я только что понял, что сохранение стека для скобок здесь излишне. Вы могли бы сделать это с помощью одного счетчика
openBrackets = 0
и увеличивать его для каждой открытой скобки, уменьшать его для каждой закрытой. Я думаю, это лучше, но, как я уже сказал, есть многое, что можно улучшить для этой функции. Это может быть обобщено на любой тип скобок и / или кавычек. Однако я оставлю все как есть.
Ответ №2:
Предполагая, что в строке есть только одно вхождение шаблона, и что никаких других вхождений ],
then ["pmeta",.*],
не может работать. Демонстрация регулярного выражения: https://regex101.com/r/4DSfVR/1
Реализация JavaScript:
inputstr = 'djfhjkdfhkhdf ["pmeta", ["ImageSelectStoreFront", null, 3, 4, 2, null, "Storefront", []]],jdkfhkjdhf';
pattern = new RegExp('\["pmeta",.*\],',"gm");
console.log(inputstr.replace(pattern,""));
Комментарии:
1. Это не работает с примером операции, опубликованным в комментариях
2. @Joxrox но это буквально не работает в примере, который вы опубликовали
3. @VLAZ верно. Я не видел вставку перед публикацией. Как я уже упоминал, это регулярное выражение работает только в том случае, если нет других случаев
],
. Я также не учел, что шаблон может содержать новые строки (s
флаг позаботится об этом).