У меня возникли проблемы с поиском решения проблемы, связанной с поиском значений в таблице HTML, на основе регулярных выражений.
На снимке экрана ниже столбец «Сумма» может содержать «,» между цифрами. Наш клиент требует, чтобы при поиске «247» (используя поле поиска) такие значения, как «2,47...» или такие, как «247» в столбце, выделялись.
Я попытался решить это с помощью регулярных выражений, но это не сработало, как ожидалось:
const regex = new RegExp(
searchTerm
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/\s+/g, "|") + ",?",
"gi"
);
Как выделить «2,47» в предыдущем примере?
const regex = new RegExp(
247
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/\s+/g, "|") + ",?",
"gi"
);
console.info('247','247'.match(regex))
console.info('2,47','2,47'.match(regex))
console.info('2.47','2.47'.match(regex))
Может ли ваш ввод позволить ввести ,
для начала? Вы, кажется, набрали «247» в своем примере, спрашивая о «24,7». Запятая в вашем коде, кажется, используется для разделения элементов поиска, вы можете подтвердить?
Почему вы изобретаете свой собственный язык поверх синтаксиса регулярных выражений — переводите поисковый запрос в регулярное выражение, используя ряд подобных сверток? Поисковый запрос обычно состоит из букв, цифр и пробелов, иногда в кавычках и обязательно с запятой (,
). Это интерпретируется как есть большинством парсеров регулярных выражений, включая RegExp
. Для всего остального он будет проанализирован, как и ожидалось — если пользователь хочет найти 2,47
, регулярное выражение 2,47
будет соответствовать строке 2,47
. Не усложняйте вещи — это то, из-за чего вы попали в беду.
В приведенном выше примере столбец, содержащий сумму, будет иметь «,» между числами. Наш клиент требует, чтобы при поиске 247 в строке поиска выделялось количество, содержащее 2,47, или любое значение, имеющее 247.
Одним из подходов для такого варианта использования было бы сгенерировать все возможные наборы строк (в приведенном выше случае ["2,47", "24,7", "247"]), а затем искать включение этих строк в данные для поиска. Когда я говорю о включении, я имею в виду data.forEach(str=>str.includes(item[0])), но это все еще кажется неправильным подходом.
Из ваших разъяснений я не вижу другого выбора, кроме как разделить вашу строку и динамически вставить необязательный ,?
между всеми вашими символами. Кажется излишним, но я не вижу другого способа игнорировать комы.
ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ благодаря markalex:
Более чистая версия, ,?
теперь добавляются только между цифрами. Таким образом, это можно сделать в конце после экранирования специальных символов и не нужны хакерские приемы, которые могут повлиять на надежность.
Также не нужно вставлять последний ,?
, он не будет иметь никакого эффекта
const regex = new RegExp(
247
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/(?<=\d)(?=\d)/g, ",?")
.replace(/\s+/g, "|"),
"gi"
);
console.info('regex: ',
247
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/(?<=\d)(?=\d)/g, ",?")
.replace(/\s+/g, "|")
)
console.info('247','247'.match(regex))
console.info('2,47','2,47'.match(regex))
console.info('2.47','2.47'.match(regex))
const regex2 = new RegExp(
'question?'
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/(?<=\d)(?=\d)/g, ",?")
.replace(/\s+/g, "|"),
"gi"
);
console.info('regex: ',
'question?'
?.toString()
.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")
.replace(/(?<=\d)(?=\d)/g, ",?")
.replace(/\s+/g, "|")
)
console.info('question?','question?'.match(regex2))
console.info('question','question'.match(regex2))
Это решение приведет к неожиданному поведению, если строка поиска содержит ?
. a?b
будет преобразовано в a,?\,??,?b,?
.
Это именно то, что я ожидал. Невероятно большое спасибо @Kaddath.
@markalex это не совсем неожиданное поведение, они просто не будут совпадать. Я исправил регулярное выражение, чтобы включить их, это немного хакерски, должен быть более чистый способ. Все равно спасибо, что заметили!
@Kaddath, под неожиданным я имел в виду, что поисковый запрос a?b
не найдет a?b
себя.
@markalex Я вижу, это термин, который имеет другое значение (и худшие последствия) по сравнению с теми, которые кодируют на C. Я думаю, что это должно быть исправлено сейчас, но они могут быть еще одним крайним случаем.
Да, верно: мой плохой. "нежелательное поведение" было бы лучше, я думаю) Что касается крайних случаев: сейчас \\
не будет соответствовать \,\
, но я сомневаюсь, что это желательно в любом случае. Что касается самого чистого решения: может быть, .replace(/(?<=\d)(?=\d)/g, ",?")
будет лучше? Он будет вставлять ,?
только между цифрами.
@Vimal Я обновил свой ответ благодаря markalex. Теперь это проще и надежнее
Ответ , похоже, охватывает основные варианты использования, но подумайте, есть ли у вас сумма не только в долларах, но и в фунтах. Именно здесь логика может дать сбой.
Другой подход может заключаться в том, чтобы хранить сумму в формате числа, например 12345, или строки «12345» в БД. Это сделало бы очень простым и эффективным выполнение запроса на поиск/поиск по этим данным.
Теперь с целью форматирования на стороне пользовательского интерфейса, например, суммы $ XX, XXX. Вы можете легко использовать функцию маски.
Это снижает сложность логики и может быть легко изменено в соответствии с требованиями клиента.
Привет, это, вероятно, должен был быть комментарий, а не ответ. Ни в вопросе, ни в моем ответе нет ничего такого, что не сработает с фунтами. В вопросе ОП нет указаний на то, что числа хранятся уже отформатированными. Этот пост посвящен сопоставлению цифр в отображаемой строке результата. Не может быть совпадения, если числа отформатированы с пробелами, как во французском языке, но ту же логику из моего ответа можно адаптировать, используя (?:\s|,)?
или что-то подобное вместо ,?
Пожалуйста, уточните, почему это должно быть выделено: вы разрешаете один
,
между результатом, или любое их количество, или любое количество знаков препинания?