#javascript #regex #alphanumeric
#javascript #регулярное выражение #буквенно-цифровое
Вопрос:
Я пытаюсь написать регулярное выражение, соответствующее фиксированной буквенно-цифровой строке, которая может содержать точки.
Это регулярное выражение должно соответствовать всем символам, кроме точек. Мне нужно было бы использовать это в Javascript search()
для сравнения двух строк. Слово для поиска: 30A10Z20
Все они соответствуют действительности:
30A1.0Z2.0
30A.10Z20
3.0.A10.Z20
3.0.A.1.0.Z.2.0.
Я написал это, но безуспешно:
^30A10Z20\.{0,1}?$
^30A10Z20\.?$
^30A10Z20(?=\.)
Любые подсказки или помощь будут очень признательны.
Комментарии:
1. Было бы проще, если бы вы просто заменили все точки, а затем проверили, равна ли строка
30A10Z20
.2. @Sweeper прав, иначе вам пришлось бы поставить .? после каждого символа…
3.
30A...............10Z20
Также допустимо?4. @georg да, это допустимо
5. @Sweeper Я думал об этом, но для меня это нехорошо. 30A10Z20 — это всего лишь часть конечной строки (например, «30A10Z20 Lorem Ipsum 3324»), и я должен соответствовать только тому, что я упомянул, чтобы я мог отформатировать его с помощью HTML-тегов (жирный шрифт). Оно должно содержать точки там, где они есть.
Ответ №1:
Я не уверен, что a RegExp
будет лучшим способом сделать то, что, я полагаю, вы хотите сделать (основываясь на ваших комментариях: попробуйте переформулировать свой вопрос). Будет ли этот фрагмент хорошей идеей?
const findTerm = (word, searchTerm) =>
word.replace(/[^a-z0-9]/gi, "") === searchTerm;
const aFewStrings = [
`something 30A1.0Z2.0 etc`,
`30A.10Z20 hithere`,
`Hello 3.0.A10.Z20`,
`The value 3.0.....A.1.0....Z.2.0. may be valid`,
`As may be the value 3.0@@@A.1.0#amp;!'Z.2.0.`,
`Bye 3.0.A.1.0.Z.2.0. ended`,
];
aFewStrings.forEach(s => {
const words = s.split(" ").map( w => findTerm(w, "30A10Z20") ? `<b>${w}</b>` : w );
console.log(words.join(" "));
});
Если вам нужны части строки (см. Ваш комментарий), вам нужно выполнить небольшой синтаксический анализ. Что — то вроде:
const findTerm = (word, searchTerm) =>
RegExp(`(${searchTerm})`, "i").test(word.replace(/[^a-z0-9]/gi, ""));
const toBold = (word, searchTerm) => {
const word2Parse = [...word];
const wordPreserved = word2Parse.slice(0);
const len = searchTerm.length;
let foundIndices = [];
let i = 0;
while (word2Parse.length) {
const noDots = word2Parse.slice(1).filter(v => !/[^a-z0-9]/i.test(v));
const next = searchTerm.length > 1 amp;amp; noDots[0] === searchTerm[1];
const found = searchTerm.length > 1
? word2Parse[0] === searchTerm[0] amp;amp; next
: word2Parse[0] === searchTerm[0];
searchTerm = found ? searchTerm.slice(1) : searchTerm;
found amp;amp; foundIndices.push(i);
i = 1;
word2Parse.shift();
}
wordPreserved[foundIndices[0]] = `<b>${wordPreserved[foundIndices[0]]}`;
wordPreserved[foundIndices.slice(-1)] = `${
wordPreserved[foundIndices.slice(-1)]}</b>`;
return wordPreserved.join("");
}
const aFewStrings = [
`something 30A1.0Z2.0 etc`,
`30A.10Z20 hithere`,
`Hello 3.0.A10.Z20`,
`The value 3.0.....A.1.0....Z.2.0. may be valid`,
`As may be the value 3.0@@@A.1.0#amp;!'Z.2.0.`,
`Bye 3.0.A.1.0.Z.2.0. ended`,
`3.0.A.1.0.Z.2.....0`,
];
const result = document.querySelector("#result");
let term = `30A1`;
result.appendChild(
Object.assign(
document.createElement("p"), {
innerHTML: `[1 String, search '30A1']: ${
(aFewStrings[3].split(" ")
.map(w =>
findTerm(w, term) ? toBold(w, term) : w)
.join(" "))}`
})
);
term = `notfound`;
result.appendChild(
Object.assign(
document.createElement("p"), {
innerHTML: `[1 String, search 'notfound']: ${
(aFewStrings[1].split(" ")
.map(w =>
findTerm(w, term) ? toBold(w, term) : w)
.join(" "))}`
})
);
term = `0Z20`;
aFewStrings.forEach(s => {
const words = s.split(" ").map(w =>
findTerm(w, term) ? toBold(w, term) : w);
result.appendChild(
Object.assign(
document.createElement("div"), {
innerHTML: words.join(" ")
})
);
});
body {
margin: 2rem;
font: normal 12px/15px verdana, arial;
}
b {
color: red;
}
<div id="result"></div>
Комментарии:
1. Это работает, очень приятно. Но есть ли способ заставить его работать только с частью строки? например, «30A1» —> <b> 30.A1</b> 0Z.20 или «Z20» —> 30.A.10<b> Z20</b>
2. Я полагаю, это можно сделать, но на самом деле это сложнее. Возможно, вы захотите упростить ввод (поэтому убедитесь, что точек там нет в первую очередь)
3. Я могу удалить точки на входе и провести сравнение. Но позже мне понадобится способ выделить текстовый формат жирным шрифтом только для того, что я нашел в первую очередь.