JavaScript урок 7. Регулярные выражения javaScript и работа с датой и временем

На уроке Вы изучите принципы работы с регулярными выражениями в javaScript, познакомитесь с объектом date для работы с датой и временем

Регулярные выражения javaScript

Назначение регулярных выражений: описание содержимого текстовой строки при помощи специальных правил с целью проверки правильности заполнения формы, отправляющей данные на сервер,

В целом, регулярные выражения — это метаязык, позволяющий проверять входные данные на шаблон.

Создание регулярных выражений (2 способа)

  1. Конструктор RegExp()
  2. let firstName = new RegExp("John");

    В представленном примере создается объект класса RegExp с именем firstName, содержащий шаблон John

  3. Присваивание шаблона переменной (короткий синтаксис)
  4. let firstName=/John/;

    В данном примере /John/ является шаблоном, а символы слеш / служат контейнером шаблона.

Если на момент написания кода мы знаем, каким будет регулярное выражение, то можно использовать слеши. Если же нам внутри регулярного выражения необходимо будет использовать переменные, то слеши использовать нельзя, они не допускают вставки переменных.
Рассмотрим примеры с регулярными выражениями javascript:

Нужно найти Регулярное выражение
asdasdasdprivetasdasdasd /privet/
privet /^privet$/
asdasdeprtviasdasdasd

asdasdeeeeeedfgdgdg

/[privet]/  или   /[privet]{6}/
SdfuiyuiewrR345 /[a-zA-Z0-9]/  или  /\w/
452341 /[0-9]/    или   /\d/
jsdf8H?& /./

 

Синтаксис регулярных выражений и методы поиска

Как искать по шаблону

Рассмотрим несколько способов поиска по шаблону:

  1. Метод search(regExp) – возвращает позицию символа с которого начинается соответствие. Возвращает -1 если строка не соответствует регулярному выражению
    Пример: Найти в строке слово Иван:

    ✍ Решение:
     

      let a=/Иван/; // шаблон регулярного выражения
      let str1="Кузьмин Иван Федорович"; // строка, в которой осуществляется поиск
      let str2="Петров Петр Петрович"; // строка, в которой осуществляется поиск
       
      if(str1.search(a)==-1) 
        alert("не найдено")
      else
        alert("найдено"); // будет найдено 
       
      if(str2.search(a)==-1) 
        alert("не найдено") // будет не найдено 
      else
        alert("найдено");
  2. Метод str.match(reg) — ищет вхождения шаблона в строке. Для предыдущего примера:

    let a=/Иван/; // шаблон регулярного выражения
    let str1="Кузьмин Иван Федорович"; // строка, в которой осуществляется поиск
    let str2="Петров Петр Петрович"; // строка, в которой осуществляется поиск
    if(!str1.match(a))  // если не найдено
      alert("не найдено")
    else
      alert("найдено"); // вывод "найдено" 
     
    if(!str2.match(a)) // если не найдено
      alert("не найдено") // вывод "не найдено" 
    else
      alert("найдено");
  3. Метод regexp.test(str) проверяет, есть ли хоть одно совпадение, если да, то возвращает true, иначе false.

    let str = "Добрый День!";
    let regexp = /день/i;
     
    alert( regexp.test(str) ); // true
  4. str.split(reg, limit) — разбивает строку по разделителю-шаблону:

    let a=/Иван/; // шаблон регулярного выражения
    let str="Кузьмин Иван Федорович Петров Петр Петрович Федоров Иван Петрович";
    document.write(str.split(a));
    //результат: Кузьмин , Федорович Петров Петр Петрович Федоров , Петрович
  5. str.replace(reg, str) — заменяет вхождения шаблона в строке:

    let a=/Иван/; // шаблон регулярного выражения
    let str="Кузьмин Иван Федорович Петров Петр Петрович Федоров Иван Петрович"; 
    document.write(str.replace(a, "Петр")); 
    //результат: Кузьмин Петр Федорович Петров Петр Петрович Федоров Иван Петрович

    Чтобы заменить все совпадения, нужно обязательно к регулярному выражению добавить флаг g:

    let a=/Иван/g; // шаблон регулярного выражения
    let str="Кузьмин Иван Федорович Петров Петр Петрович Федоров Иван Петрович"; 
    document.write(str.replace(a, "Петр"));
    //результат: Кузьмин Петр Федорович Петров Петр Петрович Федоров Петр Петрович
Что такое флаг и зачем он?
let a=/Иван/; // шаблон регулярного выражения без флага
let a=/Иван/g; // шаблон с флагом
Флаги и их значения:

  • i — поиск не зависит от регистра, т.е. нет разницы между A и a.
  • g — поиск ищет все совпадения, без флага ищет только первое вхождение.
  • m — многострочный режим.
  • s — включает режим «dotall», при котором точка . может соответствовать символу перевода строки \n.
  • u — поддержка юникода.
  • y — режим поиска на конкретной позиции в тексте.
  • Без использования флага возвращается только первое совпадение в виде массива, в котором под индексом 0 и находится совпадение:

    let str = "Добрый день! Новый день всегда к нам добр";
     
    let result = str.match(/день/); // без флага g
     
    alert( result[0] );     // день (первое совпадение)
    alert( result.length ); // 1
     
    // Дополнительная информация:
    alert( result.index );  // 0 (позиция совпадения)
    alert( result.input );  // Добрый день! Новый день всегда к нам добр (исходная строка)
    Задание js 7_1: Пользователь вводит свои имя и фамилию (два слова, разделённые пробелом).

    1. Найти в заготовленном списке введенные данные (match)
    2. Заменить найденные данные на Петр (replace)

    Список:

    Кузьмин Иван   Петров Петр   Федоров Иван
    


    При вводе, например, «Иван», в результате «Кузьмин Иван» и «Федоров Иван» должны замениться на «Кузьмин Петр» и «Федоров Петр»

    Символьные классы поиска по шаблону в javaScript

    Символьные классы — символы (латинские буквы) с впереди стоящим слешем \, которые в шаблоне несут смысловую нагрузку: на их месте должно или может находиться что-то конкретное. А что конкретное, рассмотрим ниже:

    \w Любой символ в слове (алфавитно-цифровой)
    \W Неалфавитно-цифровой символ (?, *, & …)
    Пример: следующий пример находит буква& в строке поиска, но &буква не будет найдено (конкретно: найдет rock&, но не найдет &roll):

    ✍ Решение:
     

      Для метода search:

      let a=/\w\W/; // шаблон регулярного выражения
      let str1="rock&"; // строка, в которой осуществляется поиск
      let str2="&roll"; // строка, в которой осуществляется поиск
       
      if(str1.search(a)==-1) 
        alert("не найдено")
      else
        alert("найдено"); // будет найдено 
       
      if(str2.search(a)==-1) 
        alert("не найдено") // будет не найдено 
      else
        alert("найдено");

      Для метода match:

      // ...
      if(!str1.match(a))  // если не найдено
        alert("не найдено")
      else
        alert("найдено"); // вывод "найдено" 
       
      if(!str2.match(a)) // если не найдено
        alert("не найдено") // вывод "не найдено" 
      else
        alert("найдено");

    Следующий класс:

    \s Любой пробельный символ (символы табуляции, новой строки, возврата каретки)
    \S Непробельный символ
    Пример: Ответить на вопрос, состоит ли строка только из одного слова или из нескольких слов. То есть найдется ли непробельный символ, за которым следует символ пробела:

    ✍ Решение:
     

      let a=/\s\S/; // шаблон регулярного выражения
      let str="слово1 слово2"; // строка, в которой осуществляется поиск
       
      if(str.search(a)==-1) 
        alert("одно слово")
      else
        alert("несколько слов"); // будет найдено
    \d Цифровой символ
    \D Нецифровой символ
    Пример: найдет в строке поиска, но не сможет найти р4:
    let pattern=/\d\D/;
    [\b] Используется для поиска символа забоя (backspace)
    [...] Любой символ, указанный в скобках
    [^...] Любой символ, за исключением перечисленного в скобках
    Пример: найдет ag в строке поиска, но не сможет найти ga, поскольку на первом месте должны стоять либо а, либо b, либо с:
    let pattern=/[abc] [^def]/;
    [х-у] Символы в промежутке от х до у
    [^х-у] Символы, не входящие в промежуток от х до у
    Пример: найдет ac, но не найдет ad:
    let a=/[a-d][^d-f]]/;
    let str="ad";
    if(str.search(a)==-1) alert("неверно")
    else
    alert("верно");
    {х,у} Предыдущий элемент должен быть найден не менее х раз, но не более у раз
    {х,} Предыдущий элемент должен быть найден не менее х раз
    Пример: найдет chose и choose в строке поиска, но не сможет найти chooose:
    let pattern=/cho{1,2}se/;
    ? Предыдущий элемент должен быть найден однажды или вообще не найден
    + Предыдущий элемент должен быть найден хотя бы один раз
    * Предыдущий элемент должен быть найден неограниченное количество раз или вообще не найден
    Пример: найдет abc или ас в строке, но не сможет найти abbe, поскольку символ «b» должен быть найден один раз или вообще не найден:
    let pattern=/ab?c/;
    | Должно быть совпадение либо в выражении справа, либо слева от символа |
    Пример: выдаст «верно»:
    let a=/cat|dog/;
    let str="sdfcatsdf";
    if(str.search(a)==-1) alert("неверно")
    else
    alert("верно");
    (...) Группировка всех элементов в круглых скобках в подшаблон
    Пример: осуществит поиск в строке far и for, но не fer. Пример выдаст «верно»:
    let a=/f(a|o)r/;
    let str="sdffarsdf";
    if(str.search(a)==-1) alert("неверно")
    else
    alert("верно");
    Якоря: начало строки ^ и конец $
    ^ Поиск с начала строки или же с начала первой строки в многострочных данных
    $ Поиск с конца строки или с конца последней строки в многострочных данных
    Пример: выполнит поиск слова The, если оно присутствует в начале последовательности или в начале одиночной строки:
    let pattern=/^The/;
    Проверка на полное совпадение

    Два якоря одновременно ^...$ часто используются для проверки, совпадает ли строка с шаблоном полностью.

    Пример:
    Проверим, что строка является датой в формате 12/08/11, то есть две цифры, затем двоеточие, затем ещё две цифры.

    На языке регулярных выражений это \d\d:\d\d:\d\d

    ✍ Решение:

    let correct = "12/11/11";
    let incorrect= "12/3/11";
     
    let regexp = /^\d\d:\d\d:\d\d$/;
    alert( regexp.test(correct) ); // true
    alert( regexp.test(incorrect) ); // false
    \b Позиция между знаком, входящим в слова, и не входящим в слова
    \B Позиция, не находящаяся между знаком, входящим в слова, и не входящим в слова
    Пример: найдет слово cat, за которым следует пробел. Пробел является несловарным символом:
    let pattern=/cat\b/;

    Все основные классы в регулярных выражениях

    Название класса Действие
    \w Любой символ в слове (алфавитно-цифровой)
    \W Неалфавитно-цифровой символ (?, *, & …)
    \s Любой пробельный символ (символы табуляции, новой строки, возврата каретки)
    \S Непробельный символ
    \d Цифровой символ
    \D Нецифровой символ
    [\b] Используется для поиска символа забоя (backspace)
    [] Любой из символов, указанных в скобках
    [^…] Любой символ, за исключением перечисленных в скобках
    [ху] Символы в промежутке от х до у
    [^ху] Символы, не входящие в промежуток от х до у
    {х,у} Предыдущий элемент должен быть найден не менее х раз, но не более у раз
    {х,} Предыдущий элемент должен быть найден не менее х раз
    ? Предыдущий элемент должен быть найден однажды или вообще не найден
    + Предыдущий элемент должен быть найден хотя бы один раз
    * Предыдущий элемент должен быть найден неограниченное количество раз или вообще не найден
    | Должно быть совпадение либо в выражении справа, либо слева от символа |
    () Группировка всех элементов в круглых скобках в подшаблон
    ^ Поиск с начала строки или же с начала первой строки в многострочных данных
    $ Поиск с конца строки или с конца последней строки в многострочных данных
    \b Позиция между знаком, входящим в слова, и не входящим в слова
    \B Позиция, не находящаяся между знаком, входящим в слова, и не входящим в слова
    Задание js 7_2: Извлечь из строки все числа (числом считать одну или несколько цифр, идущих подряд).
    Задание js 7_3: Пользователь вводит свои имя и фамилию (два слова, разделённые пробелом). Проверить правильность ввода, вывести сначала фамилию, затем имя.

    Рекомендации:
    Можно использовать скобочные группы для обнаружения подшаблонов

    Теперь рассмотрим действительно серьезный и часто используемый пример использования регулярных выражений javascript:

    Пример: Осуществить проверку правильности ввода в текстовое поле электронного адреса:
    Sername-name.mymail@aaa-net.tri.com.ru
    Показать решение:


    1. let a = /^[a-zA-Z0-9_]{1,}([\.-]{0,1}[a-zA-Z0-9_]{1,}){0,}@[a-zA-Z0-9_]{1,}([\.-]{0,1}[a-zA-Z0-9_] {1,}){0,}(\.[a-zA-Z0-9_]{2,4}) {1,}$/;


    2. let a = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/;

  • Эти два примера эквивалентны. Фрагменты кода одного цвета выполняют одно и то же действие.
  • Весь скрипт:
  • function checkMail(){
    let a = /^\w+([\.-]?\w+)*@\w+([\.-]?\w+)*(\.\w{2,4})+$/;
    let textMail=document.getElementById('textMail');
    let f=document.getElementById('f');
    if (textMail.value.search(a)!==-1)
    f.submit()
    else
    alert ("неверный мэйл");
    }
    Задание js 7_4:Проверьте, что строка, введенная пользователем, является десятичной дробью или целым числом. Выведите сначала целую, затем дробную части. Учтите, что разделителем может быть как запятая, так и точка.
    Задание js 7_5: Пользователь вводит путь к файлу на компьютере. Последовательно вывести имена папок, которые нужно открыть, чтобы получить доступ к файлу.
    Задание js 7_6: Составить рег. выражение, проверяющее, является ли указанная строка номером телефона в любом из следующих форматов:

    	89001234567         +79001234567
    	8 900 123 45 67     +7 900 123 45 67
    	8 (900) 123-45-67   +7 (900) 123-45-67
    	8(900)123-45-67     +7(900)123-45-67
    
    Задание js 7_7: Найдите в тексте слова, состоящие из 15 и более символов. Замените такие слова в тексте на слова вида «абстр…ние».
    Задание js 7_8: С помощью регулярных выражений удалите в тексте суффиксы -ик-:

    домик -> дом, столик -> стол, ключик -> ключ

    При этом «ик» не должен удалиться в таких словах как «икра», «абрикос» и т.п.

    Тестер регулярных выражений javaScript

    * Данный пункт материала можно пропустить. Перейдите к выполнению лабораторной работы js 7_1

    Рассмотрим также вариант примера того, как разработать Тестер регулярных выражений javaScript:

    Сценарий:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    
    // Функция осуществляет поиск по шаблону в searchstr 
    function searchForPattern(searchstr, pattern, REattributes, theResult) 
    {
    //Создание объекта регулярного выражения 
    let regExpObj = new RegExp(pattern,REattributes); 
    //Заполнение поля результата результатами поиска 
    theResult.value = regExpObj.exec(searchstr); 
    } 
    // Эта функция заменяет на replaceStr все вхождения шаблона в searchstr 
    function replacePattern(searchstr,replaceStr, pattern,REattributes,theResult) 
    {
    //Создание объекта регулярного выражения 
    let regExpObj = new RegExp(pattern,REattributes); 
    //Заполнение поля результата результатами поиска. 
    theResult.value = searchstr.replace(regExpObj,replaceStr); 
    }
    // Эта функция очищает все поля страницы 
    function clearFields(field1, field2, field3, field4, field5) 
    {
    field1.value	= "";
    field2.value	= "";
    field3.value	= "";
    field4 .value	= "";
    field5.value	= "";
    }

    Продолжение html-кода:

    <h3>Тестер регулярных выражений</h3> 
    <form name="myForm"> 
    <table board=0> 
    <tr align=right> 
    <td>Строка поиска:</td> 
    <td><input type="text" name="searchString" /></td> 
    </tr> 
    <tr align=right> 
    <td>Строка замены:</td> 
    <td> <input type="text" name="replaceString"/></td> 
    </tr> 
    <tr align=right> 
    <td>Атрибуты:</td> 
    <td><input type="text" name="REattributes"/><td> 
    </tr> 
    <tr align=right> 
    <td>Образец: </td> 
    <td><input type="text" name="pattern"/><td> 
    </tr> 
    </table> 
    <br> 
    <input type="button" value="Search for pattern" onClick="searchForPattern(searchString.value, pattern.value, REattributes.value, result)"> 
    <input type="button" value="Replace pattern" onClick="replacePattern(searchString.value, replaceString.value, pattern.value, REattributes.value, result) "> 
    <input type="button" value="Clear" onClick="clearFields(searchString, replaceString, pattern, REattributes, result)"> 
    <br /><hr /><br> Result: <input type="text" name="result"/></form>

    Объект Date для работы с датой и временем в javaScript

    Встроенные объекты javaScript:

    • Object(объекты)
    • Number (обработка чисел)
    • String (обработка строк)
    • Array (массивы)
    • Math (математические формулы, функции и константы)
    • Date (работа с датами и временем)
    • RegExp
    • Global (его свойства Infinity, NaN, undefined)
    • Function

     
    let myDate = new Date();
      

    Создание объекта date

    1. Создание объекта с текущей датой и временем
    2. let имя_переменной = new Date();

    3. Создание объекта со значением (датой), заданным в виде строки определенного формата
    4. let имя_переменной = new Date("month, day, year [hours:minutes:seconds])

      let d1 = new Date("December 15, 1997 16:57:00");
      let d2 = new Date("2000 jan 23 10:20"); /* сокращенный вариант */
    5. Создание объекта со значением, заданным с помощью числовых параметров:
    6. let имя_переменной = new Date(year, month, day [,hours,minutes,seconds])

      let d2 = new Date(1995,4,9,13,30,00);
      document.writeln(d2); // Tue May 09 1995 13:30:00 GMT+0400 (Москва, летнее время)

    Примеры использования объекта Date в javaScript:

    let today = new Date(); /* объект даты today содержит информацию о текущей дате */
    let date=today.getDate();
    alert (date);// текущее число
    let day=today.getDay();
    alert (day);// значение дня недели (0..6)
    let year=today.getFullYear();
    alert(year); //2010
    let month=today.getMonth();
    alert(month);// текущий месяц
    let hours=today.getHours();
    alert(hours);//текущий час, например 19
    let minutes=today.getMinutes();
    alert(minutes);//текущие минуты
    Лабораторная работа js 7_3. Используя методы объекта date, вывести на экран время в формате: час:минута:секунда (пример: 14:23:11)

    При этом, если секунды и минуты попадают в интервал от 0 до 10, они должны выводиться с нулем впереди.
    т.е. вместо 18:7:3 у Вас должно выводиться 18:07:03

    Дополните пропуски в коде:

    let now=new Date();
    let hours=now.getHours();
    ...
    let seconds=...;
     
    if(minutes < 10){
    	...;
    }
    if(...){
    	...;
    }
     
    document.write("Текущее время: " + hours + ":" + minutes + ":" + seconds);
    Лабораторная работа js 7_4. По текущей дате определить день недели (используя порядковый номер). Вывести результат в виде дня недели (например, «воскресенье») на экран.
    Использовать оператор переключения (switch).

    let d = new Date(); 
    ...
    Как использовать знак $ при работе с датами?

    При необходимости вывести, например, текущий год, можно использовать метод getFullYear(). Рассмотрим два результата его использования:
    Пример 1:

    let s1 = new Date().getFullYear();
    alert (s1); // 2019

    Пример 2:

    let s2 =`Cейчас идёт ${(new Date()).getFullYear()} год`;
    alert (s2); // Cейчас идёт 2019 год

    Методы объекта Date

    Метод getTime() объекта Date в javascript
    Метод getTime() возвращает время в миллисекундах, прошедшее с 1 января 1970 г.
    Рассмотрим конкретный пример с использованием метода getTime().

    Пример: Требуется узнать количество минут и часов, прошедших с 1970 г.

    ✍ Решение:
     

      let now = new Date();
      let from1970 = (now.getTime() / (1000 * 60)); // минут
      document.write(from1970);
       
      let from1970 = (now.getTime() / (1000 * 60 * 60)); // часов
      document.write("<br>"+from1970);
      Делим на 1000 чтобы получить из миллисекунд секунды

    Еще один пример:

    Пример: Определить количество дней до Нового года

    ✍ Решение:
     

      // год, месяц, день, час, мин, сек:
      let ny = new Date(2017,0,1,0,0,0);// 0-й месяц след года
      let now = new Date();
      // Кол-во дней с 1970
      let from1970 = (now.getTime() / (1000 * 60 * 60 * 24));
      document.write (from1970+"<br>");
      // Кол-во дней с 1970 до Нового года
      let from1970ToNy = (ny.getTime() / (1000 * 60 * 60 * 24));
      document.write (from1970ToNy+"<br>");
      document.write(Math.round(from1970ToNy) - Math.round(from1970));
    Лабораторная работа js 7_5. Написать функцию, которая выводит на экран дату, которая наступит через n дней от сегодняшней.

    Рекомендации к выполнению:

    • n — количество дней, которое нужно запросить у пользователя при загрузке страницы.
    • Это значение передается в функцию в качестве параметра.
    • При этом итоговую дату надо вывести в нормальном формате на русском языке.
    • Например так (пример для ввода числа 79):

      Через 79 дней будет вот такая дата:
      День недели: Воскресенье
      Число: 10
      Месяц: Октябрь
      Год: 2010

    • При этом пользователь должен ввести число от 1 до 1000.
    • Если он не попал в интервал или ввел не число, то надо вывести ошибку.
    • Проверку можно осуществлять за пределами функции.

    Подсказка. Если задание кажется сложным, не спешите смотреть ответ.
    Постарайтесь разбить задачу на как можно более мелкие шаги и для начала попробуйте написать код просто для конкретного числа дней, вообще не используя функцию.

    Заполните пропуски в коде:

    function viewDate(n){
    	let now = ...;
    	let nowMilli = now. ...;
     
    	let nowPlus79 = new Date(...);
    	let milli79 = ...;
     
    	let summaMilli = ...;
    	let itogMoment = new ... (...);
     
    	let myDays = ["Воскресенье","Понедельник","Вторник","Среда","Четверг","Пятница","Суббота"];
    	let myMonths = ...;
    	document.write("День недели: " + ...);
    	document.write("Число: " + ...);
    	...
    	...
    }
    let userDays = prompt(...);
    ...
    ...
    ...
    ...
    viewDate(...);

    Метод parse() объекта Date()
    Метод parse() в javascript — преобразует строку даты типа «Jan 11,1996» в количество миллисекунд, прошедших с полуночи 1 января 1970:

    Пример: Выведет на экран обозревателя примерно такую строку: Wednesday, May 21, 1958 10:12:00
    let d = new Date();
    d.setTime(Date.parse("21 May 1958 10:12"));
    document.write(d.toLocaleString());

    Метод UTC (год, месяц, день, час, минута, секунда) объекта Date()
    UTC (год, месяц, день, час, минута, секунда) — возвращает количество миллисекунд для даты на базе универсального координированного времени (UTC), прошедших с полуночи 1 января 1970 года.

    Пример: Определить количество дней между двумя датами, например 10 февраля 2003 и 5 марта 2003
    let date1 = new Date(2003,01,10);
    document.write(Date.parse(date1)+" "); //1044824400000
    let date2 = new Date(2003,02,5);
    document.write(Date.parse(date2)+" "); //1046811600000
    document.write(Date.parse(date2) - Date.parse(date1)+" "); //1987200000
    let days = (Date.parse(date2) - Date.parse(date1))/1000/60/60/24;
    document.write(days); // результат: 23
    Вопросы для самоконтроля:

    1. Для чего предназначен встроенный объект Date()?
    2. Какие способы задания значений для этого объекта Вы знаете?
    3. Каково предназначение методов GetMonth() и SetMonth()?
    4. Как вы думаете, где необходимо применять методы parse() и UTC()?