Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   После new RegExp null, а без new RegExp array (https://javascript.ru/forum/misc/51101-posle-new-regexp-null-bez-new-regexp-array.html)

kostyanet 24.10.2014 06:42

После new RegExp null, а без new RegExp array
 
Один паттерн. Один скопипастен в аргумент RegExp, второй компилится по синтаксису.

var d = '11-apr-1961';

var re = new RegExp('^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$');

var rx = /^(\d{1,2})(\/|-)([a-zA-Z]{3})(\/|-)(\d{4})$/;

d.match(re);
/*
null
*/
d.match(rx);
/*
11-apr-1961,11,-,apr,-,1961
*/


В чем тут секрет?

kostyanet 24.10.2014 06:45

Упс, день космонавтики 12 апреля, надо ж, забыл.

Сразу второй вопрос задам. Как переделать среднюю часть которая отвечает за месяц, чтобы она ловила не только текст, но и число месяца (1-12). При этом текст будет русский, а длина текста от 3 до полного названия месяца.

И еще, оказывается в регах пробел как пробел имеет значение. А какой символ с экраном его заменяет конкретно? Чтобы не спейс передавать, а конкретную букву. Потому что мне надо будет заменить / на пробел, а пробелы сами знаете, вещь неустойчивая.

ruslan_mart 24.10.2014 06:55

kostyanet, дело в том, что в RegExp нужно экранизировать служебные символы в двойне, так как мы передаём строку, а в строке, как привило, все обратные слэшы служат для экранизации, например, тех же кавычек.

var re = new RegExp('^(\\d{1,2})(\\/|-)([a-zA-Z]{3})(\\/|-)(\\d{4})$');


Цитата:

Сообщение от kostyanet
А какой символ с экраном его заменяет конкретно?

\s

kostyanet 24.10.2014 07:13

Ага, спасибо, я уже нашел и вспомнил что напарывался на этот сук. На лбу бы вытатуировал, но экран у меня не блестящий, не вижу себя. Начинаю в срач-паде проводить эксперименты и забываю что надо же саму строку оформить. Через атрибут pattern все передается слава богу как есть.

Насчет \s - это не только space, это вообще все что на него похоже. Табы, переносы (кажется) и прочая хрень.

С пробелом проблема визуального характера. У него ширина зависит от шрифта, два пробела могут выглядеть как один, или ни одного как пробел. Хотелось такой конкретный символ, чтобы пробел было видно, может там код его ввести?

kostyanet 24.10.2014 07:24

В общем на русский от 3 до 7 сделал, а как числа для месяца туда добавить?

var d = '12 апреля 1961';


var rx = /^(\d{1,2})( |-)([а-яА-Я]{3,7})( |-)(\d{4})$/;

d.match(rx);


/*
12 апреля 1961,12, ,апреля, ,1961
*/


Кажется вот так

Код:

var rx = /^(\d{1,2})( |-)([а-яА-Я0-9]{2,7})( |-)(\d{4})$/;
но пришлось уменьшить минимум, то есть можно написать теперь 12 ап 1967

Вот что делает \s

var d = '12\tян 1961';


var rx = /^(\d{1,2})(\s)([а-яА-Я0-9]{2,7})(\s)(\d{4})$/;

d.match(rx);


/*
12	ян 1961,12,	,ян, ,1961
*/

danik.js 24.10.2014 08:20

Цитата:

Сообщение от kostyanet
два пробела могут выглядеть как один

/ {2}/
Сразу видно что пробела два )

kostyanet 24.10.2014 08:54

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

рони 24.10.2014 09:17

kostyanet,
:-?
d.split(/\s+/)

terminator-101 24.10.2014 09:40

Цитата:

Сообщение от kostyanet
Хотелось такой конкретный символ, чтобы пробел было видно, может там код его ввести?

Я че то не знаю про такой. По идее, можно вот так /foo[ ]bar/
, я думаю. Или вот так /foo(?: )bar/

kostyanet 25.10.2014 04:01

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

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

$pat = '^(0[1-9]|[12][0-9]|3[01])[- .](0[1-9]|1[012]|янв|фев|мар|апр|мая|июн|июл|авг|сен|окт|ноя|дек)[- .](19|20)\d\d$';


Как сделать чтобы совпадало по началу названия, ну как в функции php strncmp(str1,str2,n) - где n количество символов от начала.

То есть рега матчит дату 12 янв 1987, а 12 января 1987 не матчит. Помогите regex-идиоту.

kostyanet 25.10.2014 04:07

При чем тут php. Из него валятся паттерны в атрибуты, а из атрибутов в js, поэтому приходится выбирать из подмножества совпадающих по лексике и логике.

Я было обрадовался с предыдущим вариантом, но накатав функцию превращения русских дат в timestamp понял что ошибки будут теперь выводится в фазе записи в БД, а надо чтоб в фазе валидации, то есть на 1 фазу раньше.

kostyanet 25.10.2014 06:38

Походу задробить, ну их нафиг эти названия, народ и так-то печатать не горазд, все равно числом вводить будет. Кроме того наконец-то дочитал мануал по php strtotime() которая, оказывается, понимает нашу нотацию просто по отсутствию американских косых. То есть 09/11/2001 - посчитает по-ихнему, а 11 09 2011, или 11.09.2001, 11-09-2001, 11\t09\t2001 - по-нашему.

Базовую регу натырил тут - http://www.regular-expressions.info/dates.html - в самом низу

terminator-101 25.10.2014 11:20

Цитата:

Сообщение от kostyanet
То есть рега матчит дату 12 янв 1987

Вот это вроде работает
re=/^(янв|фев|мар|апр|мая|июн|июл|авг|сен|окт|ноя|дек)[а-яА-Я]{0,5}$/
arr="вмая ма января январряло февраля марта апреля мая июня июля августя сентября октября ноября декабря".split(" ")
arr.forEach(function(m){console.log(m, m.length, re.test(m))})

UPD полностью вот так попробуй, хотя полностью твою регулярку не проверял, хз
pat = /^(0[1-9]|[12][0-9]|3[01])[- .](янв|фев|мар|апр|мая|июн|июл|авг|сен|окт|ноя|дек)[а-яА-Я]{0,5}[- .](19|20)\d\d$/

s1="10 янв 1999"
s2="10 января 1999"
s3="10 январяяяяяяя 1999"
alert([pat.test(s1), pat.test(s2), pat.test(s3)])
console.log(s1.match(pat), s2.match(pat), s3.match(pat))

kostyanet 25.10.2014 11:57

Да какой нах сплит, это же текстовое поле которое наравне с другими проверяется сугубо по им самим предоставленному паттерну. Ну то есть несколько более высокий уровень абстракции чем сплит.

Хера на месяцы текстом, в общем.

Собственно оно текстовое именно потому что type="data" обсижен хромированными мухами. Я лично не собираюсь нацию переучивать на ISO8601, поэтому сделал type="text"

terminator-101 25.10.2014 12:06

kostyanet,
Ты ебанулся? Я сплитом просто массив сформировал, чтобы регуляркой по нему пройтись, проверить кусок твой сомнительный. Смотри UDP выше.

terminator-101 25.10.2014 12:19

kostyanet,
Если числовой формат месяца еще нужен, то вроде так
pat = /^(0[1-9]|[12][0-9]|3[01])[- .](0[1-9]|1[012]|(янв|фев|мар|апр|мая|июн|июл|авг|сен|окт|ноя|дек)[а-яА-Я]{0,5})[- .](19|20)\d\d$/

s1="10 янв 1999"
s2="10 января 1999"
s3="10 11 1999"
s4="10 14 1999"
alert([pat.test(s1), pat.test(s2), pat.test(s3), pat.test(s4)])

kostyanet 25.10.2014 12:38

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

Если юзер впишет 30 февраля 1987 то х ему а не открытка на ДР, он не рождался вообще!

То есть пришлось-таки выводить эксепшн из фазы подготовки к записи.

рони 25.10.2014 12:45

Цитата:

Сообщение от kostyanet
Если юзер впишет 30 февраля 1987

Цитата:

вариант невозможности выбрать несуществующую дату
http://javascript.ru/forum/dom-windo...tml#post263897

terminator-101 25.10.2014 12:52

kostyanet,
Цитата:

Сообщение от kostyanet
невозможно проверить практическими регами

Можно, если потрахаться, но не нужно. Будешь отсеивать 99% случаев, это уже хорошо. Идеально, как правило не надо.

kostyanet 25.10.2014 12:53

Разрешаю вам потрахаться.


Часовой пояс GMT +3, время: 04:54.