regexp и русский язык - проблема с группировкой паттерна

Обсуждение программ nnCron и nnCron LITE

regexp и русский язык - проблема с группировкой паттерна

Postby elos » Sun, 17 Aug 2014, 20:08

Необходимо отпарсить файл test.txt, вытащив из строк два шаблона - операция(вкл/выкл) и номер телефона.
Далее, в зависимости от значения первого паттерна мне надо создать некий файл... Застрял как раз на первом шаблоне.
Мне надо использовать (Выкл|Вкл), а оно как раз и не срабатывает...
Начинал пробовать на RegexBuddy - там все шаблоны находились.
При переносе в nncron - не работает логическое ИЛИ в паттерне. Работает только при одном значении, но не двух.
Уже на двух машинах попробовал. До этого уже замечал, что с русским языком в regexp.dll что-то не то - не отрабатывал ключ "не различать регистр" для русского языка.

Что я делаю не так?

тестовый вариант test.txt
Code: Select all
"Выключение\Включение\",,,,,,,,,,,,,,,,,,,
,,,,,,,,,,,,,,,,,,,
,"10034230","19.05.14","Выключение",,"Телефон","_","4832415892",,,"Новая",,,,,,"?","?",,
,"10034127","19.05.14","Выключение",,"Телефон","_","4832414652",,,"Новая",,,,,,"?","?",,
"241",,,,"0812-1419-241",,"Кол-во: 2",,,,"Новая",,,,,,,,,
,"11078873","12.08.14","Включение",,"Телефон","_","4832417254",,,"Новая",,,,,,"?","?",,"
,"11082472","12.08.14","Включение",,"Телефон","_","4832416223",,,"Новая",,,,,,"?","?",,"

Code: Select all
#( test_xls1
\ NoActive
WatchHotKey: "^+i"
Action:
\ все преобразованные txt-файлы парсим, создавая файл команд
FILE-CREATE: "C:\ELSIS\nnLOG\session_log.txt"

S" D:\MailABLO\unpack\test.txt" READ-BY-LINE
   FOUND-LINE

\       S" /(вкл|выкл).+483(2\d{6})/i" RE-MATCH                             \ пусто
\       S" /(Вкл|Выкл).+483(2[0-9][0-9][0-9][0-9][0-9][0-9])/i" RE-MATCH    \ пусто
\       S" /.+483(2[0-9][0-9][0-9][0-9][0-9][0-9])/" RE-MATCH               \ только телефоны
\       S" /.+483(2[0-9]{6})/i" RE-MATCH                                    \ только телефоны
\       S" /.+(\xC2\xFB\xEA\xEB|\xC2\xEA\xEB).+483(2[0-9]{6})/" RE-MATCH    \ пусто
\       S" /.+(Выкл|Вкл).+483(2[0-9]{6})/" RE-MATCH                         \ пусто
       S" /.+(Выкл).+483(2[0-9]{6})/" RE-MATCH   \ находим оба паттерна

        IF
         FILE-APPEND: "C:\ELSIS\nnLOG\session_log.txt" "%$1%    %$2% %crlf%"
        THEN
;READ-BY-LINE
BEEP: 300 1000
)#

На всякий случай - READ-BY-LINE от 17.05.2009г. Для старой версии надо FOUND-LINE убрать.

nncron.exe v 1.93b13 Build 1172 18.03.2013
tm.exe v 1.93b13 Build 599 18.03.2013
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby Morituruz » Sun, 17 Aug 2014, 20:36

Про неразличимость регистра для русского языка вроде никто и не обещал, а вот насчёт вертикального слеша в справке написано, что это для паттернов, т.е. надо так: (Вкл)|(Выкл)
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Mon, 18 Aug 2014, 10:35

т.е. надо так: (Вкл)|(Выкл)
Можно и так, и эдак. Но попробую - "не заметил" первый пример. Спасибо!
\ совпадает со словами 'cat' или 'mouse'
/(cat)|(mouse)/
\ совпадает со словами 'dogs', 'doggie'
/dog(s|gie)/

Про неразличимость регистра для русского языка вроде никто и не обещал
Но и не отрицал отсутствие!

Откуда regexp.dll бралась? Вроде где-то попадалось, что она в чём-то урезана...
Хочется понять - я туплю или она всё же работает в определённом случае (пробовал в W2k и Win7, надо в W2k)? Тогда хочется знать её точный алгоритм работы.
Ведь в RegexBuddy шаблон отрабатывает нормально.
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby Morituruz » Mon, 18 Aug 2014, 10:53

elos wrote:Можно и так, и эдак.

Нет, нельзя :)
elos wrote:Но и не отрицал отсутствие!

Странная логика: если не написано — значит есть.
elos wrote:Ведь в RegexBuddy шаблон отрабатывает нормально.

Там другая библиотека. Диалектов регэкспов — вагон.
User avatar
Morituruz
 
Posts: 725
Joined: Sun, 14 Oct 2007, 01:51

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Wed, 27 Aug 2014, 13:19

elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Thu, 04 Sep 2014, 15:38

Ниженаписанное - не желание развести народ на полемику, а попытка разобраться с реализацией nncron-овского regexp-движка (или диалекта) и файлом помощи.

Чтение файла помощи nncron в сочетании с чтением книг типа "Регулярные выражения" Джефри Фридла или "Regular Expressions Cookbook" Jan Goyvaerts и Steven Levithan вызывает временами недоумение.

Сначала спотыкаешься о спецсимвол \d. \d не число (как написано в help), а цифра.

Из Cookbook:
"Последовательностям \d и [\d] соответствует один цифровой символ."

Из моего кода:
Code: Select all
SET restest2=30/08/2010 07:57:42.718,9916,2000,2144,HpZPort,POLUCHATELCHP,PrintOpenJob OK, Port="172.19.5.2" Title="38045-36.ps"
SET regtest2=/((\d+\/)+\d+\s(\d+\:)+\d+\.\d+)[\,\w\s\=\"\.]+Title\=\"(\w+\-\w+\.ps)\"/i

Потом натыкаешься на модификатор /.../i и поиск русского текста. Некоторым решением могут быть два пути. При поиске русского текста внутри файла с помощью READ-BY-LINE: лучше regexp с длинным русским текстом задать, например, малым регистром, а найденную строку (FOUND-LINE) соответственно конвертировать в малый регистр (плагин recode.spf). Если же regexp с русским текстом короткий - проще в нём употребить диапазоны, типа /[вВ][ыЫ][кК][лЛ])/.

Последнее откровение - особенности работы логического ИЛИ в регулярном выражении.

Сначала о терминах:
В nncron-help почему-то применяется название паттерн к части регулярного выражения, ограниченного круглыми скобками.
В книгах же и в сети - Pattern, он же Mask - это последовательность символов и так называемых метасимволов, описанных специальным образом. Это то, что мы помещаем в nncron-regexp в слеши "/".
Часть паттерна, ограниченная круглыми скобками - это уже subpattern или submask.

В nncron-help явно описано только одно применение круглых скобок (round brackets) - "Сгруппировать символы в один паттерн и запомнить". То, что у круглых скобок несколько применений и все они тут как раз и работают - это явно не написано.
Применение круглых скобок по книгам и примерам из сети:
ограничение области действия в конструкции выбора "|";
группировка символов для применения квантификаторов (например, ? и *);
<запоминание> текста, который совпал с находящимся в них подвыражением.

После всего этого я соответственно жду, что выражение /(вкл|выкл)/ при поиске найдет и запомнит в, допустим, $1 или "вкл" или "выкл". Что подтверждает проверка в RegexBuddy.
(Кстати, мне для программы может быть нужен только такой вариант. Чтобы программа была менее сложная и более доступная для понимания логики работы)

В nncron-help же в явном виде записаны 2 примера применения круглых скобок в сочетании с "|" (она же "труба", она же pipe) и ждём работоспособности в обоих описанных в help случаях.
Code: Select all
\ совпадает со словами 'cat' или 'mouse'
/(cat)|(mouse)/
\ совпадает со словами 'dogs', 'doggie'
/dog(s|gie)/

Посмотрим как ожидаемое и описанное сочетаются на практике имеющегося у нас regexp-движка.
(Перед этим в RegexBuddy проверил - он что perl, что в pcre версии движка находит ОБА искомых слова во всех вариантах regexp.)

Для чистоты эксперимента забудем про русский язык и посмотрим как логическое ИЛИ влияет на поиск (помним, что $0 - вся найденная последовательность):
Проверяем в консоли nncron вариант:
\ совпадает со словами 'cat' или 'mouse'
/(cat)|(mouse)/

Code: Select all
S" dklkdogshkadoggieacbnhdhg483jlkh" S" /(dogs)|(doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
1
dogs
dogs
 Ok
dogs+doggie: при наличии в строке обоих паттернов находит только первый шаблон и не обращает внимания на последующий - логика работы ИЛИ.

Заодно замечаем ошибку в help "RE-MATCH возвращает TRUE", а у нас 1 ! Но мы, конечно, помним, что всё ненулевое - TRUE.
Code: Select all
TRUE .
-1  Ok

Code: Select all
S" dklkdoghkadoggieacbnhdhg483jlkh" S" /(dogs)|(doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
1
doggie

doggie Ok
dog +doggie: подтверждение, что вторая скобка тоже работает

Это же по другому: первая скобка запоминает пустую строку
Code: Select all
S" dklkdoghkadoggieacbnhdhg483jlkh" S" /(dogs)|(doggie)/" RE-MATCH .
1  Ok
$1 TYPE
 Ok
$2 TYPE
doggie Ok

Code: Select all
S" dklkdoghkadoggieacbndoguhdhg483jlkh" S" /(dogs)|(doggie|(dogu))/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE $3 TYPE
1
doggie

doggie Ok
S" dklkdogshkadoggiacbndoguhdhg483jlkh" S" /(dogs)|(doggie|(dogu))/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE $3 TYPE
1
dogs
dogs
 Ok
S" dklkdoghkadoggiacbndoguhdhg483jlkh" S" /(dogs)|(doggie|(dogu))/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE $3 TYPE
0


 Ok
S" dklkdoghkadoggiacbndoghdDOGhg483jlkh" S" /(dogs)|(doggie|(dogu)|(DOG))/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE $3 TYPE $4 TYPE
0


 Ok
Ищется только для первой "трубы"... Нигде не написано, что ИЛИ может быть только один.

Теперь проверяем вариант:
Code: Select all
\ совпадает со словами 'dogs', 'doggie'
/dog(s|gie)/

Code: Select all
S" dklkdogshkadoggieacbnhdhg483jlkh" S" /(dogs|doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
0


 Ok
S" dklkdoghkadoggieacbnhdhg483jlkh" S" /(dogs|doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
0


 Ok
S" dklkdogshkadoggacbnhdhg483jlkh" S" /(dogs|doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
0


 Ok
S" dklkdogshkadoggieacbnhdhg483jlkh" S" /.+(dogs|doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
0


 Ok
при наличии обоих или одного из двух шаблонов в искомой строке - почему-то ничего не нашлось!
Code: Select all
S" dklkdogshkadoggieacbnhdhg483jlkh" S" /dog(s|gie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
doggie
gie Ok
S" dklkdogshkadoggacbnhdhg483jlkh" S" /dog(s|gie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
0

 Ok
S" dklkdogshkadoggieacbnhdogudhg483jlkh" S" /.+dog(s|gie|u)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
1
dklkdogshkadoggie
gie
 Ok
dogs+doggie: нашлась, почему то только вторая часть... RegexBuddy показывает оба слова

Избавляемся от "трубы":
Code: Select all
S" dklkdogshkadoggieacbnhdhg483jlkh" S" /(dogs).+(doggie)/" RE-MATCH . CR $0 TYPE CR $1 TYPE CR $2 TYPE
1
dogshkadoggie
dogs
doggie Ok

Вывод (лично для себя): по возможности отказаться от применения логического ИЛИ, ибо не работает как ожидаешь.

Для текущей реализации nncron-regexp-engine оператор логического ИЛИ применим только в варианте /(pattern1)|(pattern2)/,при этом под паттерном надо понимать только последовательности в круглых скобках, а не всё регулярное выражение. И не забывать принцип работы ИЛИ применительно к обрабатываемому тексту (на случай всех вариантов выбора в одной строке)...
Вариант /.+(pattern1|pattern2)/ упорно ищет только pattern2.

При наличии в regexp логического ИЛИ (|) в данной реализации должны осознавать - работает только первый ИЛИ, остальные не отрабатываются(?) ...

До расширенных операторов пока руки ещё не дошли - что там обнаружится?


Morituruz wrote:Странная логика: если не написано — значит есть.

Если написано - не значит, что написано всё или работает как надо. Так всё можно списать на волшебное слово "диалект".

Тыкните носом где напутал/запутался.
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby VoidVolker » Thu, 04 Sep 2014, 22:15

Code: Select all
S" dogsf" S" /dog(s|ef)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
dogsf
sf Ok

Так стало чуть яснее? Для "или" нужен паттерн (субпаттерн) - это либо одиночный символ либо группа символов (другое регулярное выражение). Т.е. в случае, описанном в мануале, совпадение между строкой и регулярным выражением будет следующее:
\ совпадает со словами 'dogs', 'doggie'
/dog(s|gie)/

В мануале четко указаны две строки через запятую: т.е. подразумевается, что данное регулярное выражение сработает, если ему дать строку один или строку два.
elos wrote:при наличии обоих или одного из двух шаблонов в искомой строке - почему-то ничего не нашлось!

Не нашлось потому, что строка не совпадает с регулярным выражением, ибо регулярное выражение /(dogs|doggie)/ ищет вот такие строки:
dogsoggie
dogdoggie

Code: Select all
S" dogsoggie" S" /(dogs|doggie)/" RE-MATCH . CR
1
 Ok
S" dogdoggie" S" /(dogs|doggie)/" RE-MATCH . CR
1
 Ok

А там строки с кучей других символов и всего остального.
elos wrote:Вывод (лично для себя): по возможности отказаться от применения логического ИЛИ, ибо не работает как ожидаешь.

Так что все работает именно так, как указано в мануале - давно пользуюсь регулярными выражениями и всегда они работали именно так, как этого ожидаешь.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Fri, 05 Sep 2014, 07:52

Спасибо! Пошёл переваривать.
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby VoidVolker » Fri, 05 Sep 2014, 09:58

Для этого и существует форум :) Так что если еще что-то непонятно будет - велкам. Кстати, в свойствах regexp.dll можно увидеть его дату - 03.09.2001, так что сравнивать его с современными движками будет не совсем правильно, т.к. за прошедшее время многие стандарты поменялись и расширились.
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Tue, 09 Sep 2014, 12:39

Да, тему надо было по другому назвать - "regexp - проблема выбора паттерна"

Вначале фрагменты из Фридла...
Не путайте конструкцию выбора с символьным классом.

Класс '[abc]' и конструкция выбора '(а | b | c)' фактически означают одно и то же, но эта эквивалентность относится только к конкретному примеру.

Символьный класс совпадает ровно с одним символом, какой длины ни был бы список допустимых символов.
С другой стороны, конструкция выбора может содержать альтернативы произвольной длины, текстуально не связанные друг с другом: '\<(1, 000,00011million | thousandthou)\>'.
В отличие от символьных классов, конструкции выбора не могут инвертироваться.


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

Символьные классы, можно считать, обладают собственным мини-языком (и, в частности, собственными представлениями о метасимволах),
тогда как конструкция выбора является частью <основного> языка регулярных выражений.

Символьный класс является отдельным <элементом>, применение к которому метасимволов +, ? и т. д. не требует круглых скобок.

После чтения фрагмента ответа VoidVolker "это либо одиночный символ", перечитывания Фридла и осмысления/тестирования наступило прозрение.
Всё-таки текст описания регулярных выражений, по сути, брался из описания синтаксиса библиотеки colorer с незаметным упоминанием на форуме в районе 2005 года "возможно, и сам чего-то добавил".

Читая Фридла и доки на различные диалекты regexp-ов, ждёшь соответствия "конструкция выбора может содержать альтернативы произвольной длины, текстуально не связанные друг с другом: '\<(1, 000,00011million | thousandthou)\>' " описанию nncron-help.
На практике же видим другое...
Code: Select all
S" dogsf" S" /dog(s|e|f)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
dogs
s Ok
S" dogesf" S" /dog(s|e|f)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
doge
e Ok
S" dogfesf" S" /dog(s|e|f)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
dogf
f Ok
S" dogsf" S" /dog(s|ef)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
1
dogsf
sf Ok
S" dogesf" S" /dog(s|ef)/" RE-MATCH . CR $0 TYPE CR $1 TYPE
0

 Ok
S" dogesf" S" /dog(s|ef)es/" RE-MATCH . CR $0 TYPE CR $1 TYPE
0

 Ok
Вывод: в данной реализации регулярных выражений '|' является метасимволом символьного класса (символьный класс представляет один символ целевого текста, какой длины ни был бы список допустимых символов.), а не оператором (согласно nncron-help) регулярного выражения.
По простому - рассматриваются одиночные символы слева/справа от '|'. Альтернативами являются одиночные символы, а не произвольной длины строки, они же " либо группа символов (другое регулярное выражение)".
После такого всё становится однозначно прозрачно!
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby ANR Daemon » Sat, 13 Sep 2014, 01:40

Вы делаете выводы на основании неполных данных.
Если коротко, вы не понимаете, как именно работает сравнение регэкспов и что является результатом этого сравнения.
ANR Daemon
 
Posts: 234
Joined: Mon, 26 Feb 2007, 22:59

Re: regexp и русский язык - проблема с группировкой паттерна

Postby elos » Sat, 13 Sep 2014, 12:40

ANR Daemon wrote:Вы делаете выводы на основании неполных данных.

Можно источник полных данных? Конкретно для этой реализации...
Я себя знатоком не считал, пошёл к человеку, на Perl-е более десятка лет работающим - он смотрел с недоумением.
elos
 
Posts: 665
Joined: Tue, 25 Apr 2006, 11:15

Re: regexp и русский язык - проблема с группировкой паттерна

Postby ANR Daemon » Sun, 21 Sep 2014, 19:09

При этом вы опять утаиваете львиную долю информации. Что именно вы показали этому человеку, и чем именно он объяснил своё недоумение?
ANR Daemon
 
Posts: 234
Joined: Mon, 26 Feb 2007, 22:59


Return to nnCron forum (Russian)

Who is online

Users browsing this forum: Bing [Bot] and 1 guest