Pull to refresh

Comments 20

Если один из ваших номеров (который мог бу существовать на деле) не подошел, пишите, дополню.

Спасибо, но лучше я сам у себя проверю и если понадобится — исправлю.

“У вас есть проблема. Вы решили использовать регулярные выражения чтобы её решить. Теперь у вас две проблемы.”

Обычно телефонные номера проходят валидацию, так что все равно к какому-то определенному формату приводить надо. Ну и хранить в БД "как юзер ввёл" тоже, на мой взгляд, не очень кошерно.


Но как пример сферического коня в вакууме, вполне нарм.

Оооо! «Мама, я постиг простенькие регулярки.» Не нужно так, этот код потом людям придется сопровождать.


  1. Откусили голову (если есть) по шаблону /(?<=+|\A)\d+(?=\D)/
  2. Выбросили все, что не цифра — из того, что осталось.
  3. Добавили код страны (если п. 1 вернул значение), или дефолт.

Две строчки кода, внятные и короткие.

По-вашему это номер телефона: (+12 (123 456 789-000

это не номер телефона — но не из-за скобок а потому что там на три цифры больше чем нужно для странового кода +1

а наличие\отсутствие скобок… модем, мобильный телефон, астериск — они просто проигнорируют эти символы и наберут строку "(+12 (123 456 789-" как нормальный североамериканский номер.
Код страны может быть больше чем 2 цифры: +380 57 700 0046 (Укртелеком, г. Харьков, Украина)
Код города может быть больше чем 3 цифры: +7 (86196) 7-19-86 (Россельхозбанк, г. Тихорецк, Краснодарский край, Россия)
type Context = {
    readonly offset: number;
    readonly filtered: string;
}

function hidePhone(phone: string, replaceTo = '*', elemsHide = 4, sliceFromback = 4): string {
    const rangeStart = sliceFromback;
    const rangeEnd = sliceFromback + elemsHide;

    return Array.from(phone).reduceRight((ctx: Context, char: string): Context => {
        const isDigit = char >= '0' && char <= '9';
        const offset = ctx.offset + (isDigit ? 1 : 0);
        const filteredChar = isDigit && (offset >= rangeStart && offset < rangeEnd) ? replaceTo : char;
        const filtered = filteredChar + ctx.filtered;
        return { offset, filtered };
    }, { offset: -1, filtered: '' }).filtered;
}

console.log(hidePhone('+12(345) 678-90-12 ;D'));
А ещё есть локальные номера. В том же Петербурге — не обязательно указывать префикс 812 для локальных вызовов. Т.е. здесь больше вопрос являются ли номера нормализованными или нет. Кстати, это вызывает проблемы, т.к., скажем, по базе 812*******, +7812******* и 8812******* тупым сравнением являются разными номерами. А ещё есть прикол с мобильными с прямыми городскими. Тема обширная
Удивительно причудливое решение. Возможно, так будет проще?

phoneNumber.replace(/\d/g, (current) => {
  this.counter = this.counter || 0; 
  this.counter++;  
  return (this.counter > 3 && this.counter < 7) ? '*' : current
  }
)


Вместо 3 и 7 можете вставлять какие-то свои min и max.

Так проще, но по условиям нужно идти с обратной стороны.

JS-way!

phoneNumber.split('').reverse().join('').replace(/\d/g, (current) => {
  this.counter = this.counter || 0; 
  this.counter++;  
  return (this.counter > 3 && this.counter < 7) ? '*' : current
  }
).split('').reverse().join('');


Хотя смысл это имеет разве что эзотерический. Что значит ваш комментарий про обратную сторону?

Я только сейчас обратил внимание на вашу дописку к комментарию. "Идти с обратной стороны" значит, что если у вас последовательность варьруемой длины (то 8 знаков, то 15), вам всегда нужно оставить последние 4 цифры целыми, и закрасить еще 4 цифры с конца.


Впрочем, с эзотерическим смыслом соглашусь, т.к. если уж хранить ненормализованные данные, так нефильтрованные, а раз фильтровать, так все равно нужно предварительно нормализовать.

Вики подсказывает, что форматов телефонов очень много и там все сложно, а значит регулярки выкидываем на свалку и делаем простой LL парсер. А ещё лучше — libphonenumber.

Лет 10 назад аутсорсили для одного российского сотового оператора плагины для IE, FF, Outlook. Задача была находить на странице телефонные номера, подсвечивать их, добавлять флажок и пару кнопок.
Так вот, сначала пробовали регулярками. Но тестировщики постоянно находили примеры где регулярки не работают. Потом я плюнул и написал обычную функцию на js, как когда-то в универе на си делал. Заработало, причём на порядок быстрее регулярок (на тестовой странице было 100+ номеров с разным контентом).
Ещё достаточно нетривиальной задачей было определение страны по номеру телефона. Во-первых разные форматы номеров, как локальных так и международных. Во-вторых, коды стран от 1 до 4 цифр (см. Википедию). США с Канадой где номера могут на +1 начинаться и т.п.

А есть еще буквенные номера вроде 1-900-MICROSOFT-22 (на самом деле это цифровой номер, а буквы просто матчатся в цифры, но людям так проще запоминать)
А потом хакер пытаясь взломать какого-то человека — узнаёт разные наборы цифр на разных сервисах и получает цельный номер. Были прецеденты.

Хороший вариант — оставлять последние две цифры, как делают некоторые крупные сайты (конкретно инстаграм сейчас вспомнился).

Кроме того из номера следует убрать всё кроме цифр.

В такой постановке — это будет существенно более простая задача.
А потом оказывается, что у пользователя два номера, и у обоих последние две цифры совпадают. Были прецеденты.
Only those users with full accounts are able to leave comments. Log in, please.