Поиск в txt файле и вывод строки с найденным совпадением

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

Поиск в txt файле и вывод строки с найденным совпадением

Postby Magsky » Thu, 11 Oct 2007, 16:07

Помогите решить задачу:
Нужно сделать напоминалку дней рождения.
Есть текстовый файл содержащий записи примерного вида:
Иванов Иван Иванович 01.01.1901
Петров Петр Петрович 02.02.1902

Нужно выдавать целую строку в подсказке исходя из совпадения по сегодняшней дате.Так как не программист, ломаю голову,пока двигаюсь в таком направлении и не знаю как сравнить содержимое массива с содержимым текстового файла:
#( Чтение_файла
NoActive
CREATE birth_arr 256 ALLOT
Action:
ShowNormal NormalPriority
Day@ N>S birth_arr PLACE
Mon@ N>S birth_arr +PLACE
MSG: "Array contents: %birth_arr COUNT%"
S" D:\tst.txt" FILE birth_arr COUNT RE-MATCH
IF MSG: "YES"
ELSE MSG: "NO"
THEN
)#


Ясно что не работает, но по-другому не могу придумать как решать проблему.
Magsky
 
Posts: 3
Joined: Thu, 11 Oct 2007, 08:45

Postby AlikasS » Thu, 11 Oct 2007, 16:29

посмотри файл example.tab в каталоге nncron, там есть пример, задача birthdays
User avatar
AlikasS
 
Posts: 1437
Joined: Wed, 28 Jun 2006, 05:39
Location: Khabarovsk

Re: Поиск в txt файле и вывод строки с найденным совпадением

Postby SaMM » Fri, 12 Oct 2007, 15:00

Magsky wrote:Помогите решить задачу:
Нужно сделать напоминалку дней рождения.
Есть текстовый файл содержащий записи примерного вида:
Иванов Иван Иванович 01.01.1901
Петров Петр Петрович 02.02.1902

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

Code: Select all
#( test
NoActive
Action:
    READ-BY-LINE: "C:\file.txt"
        2DUP S" *%DD%.%MM%.%YYYY%*" EVAL-SUBST WC-COMPARE IF
            MsgBox
        ELSE
            2DROP
        THEN
    ;READ-BY-LINE
)#
SaMM
 
Posts: 236
Joined: Fri, 25 Aug 2006, 12:33

Postby Magsky » Tue, 16 Oct 2007, 15:12

Вообщем воспользовался стандартным примером,вроде устраивает.
Только одна беда почему он некорректно работает с сетевыми дисками,то бишь не находит txt файл на сетевом диске?
Magsky
 
Posts: 3
Joined: Thu, 11 Oct 2007, 08:45

Postby SaMM » Tue, 16 Oct 2007, 16:13

Magsky wrote:Вообщем воспользовался стандартным примером

А чем READ-BY-LINE плох?
Magsky wrote:Только одна беда почему он некорректно работает с сетевыми дисками,то бишь не находит txt файл на сетевом диске?

Ты задачу авторизовал?
SaMM
 
Posts: 236
Joined: Fri, 25 Aug 2006, 12:33

Postby Magsky » Tue, 16 Oct 2007, 16:47

Сейчас попробую авторизовать.
Твой вариант попробывал ругается именно на слово READ-BY-LINE.
Дальше не стал разбираться.
Очень был бы благодарен если бы ты написал пару комментариев в своем варианте,чтобы было легче разобраться,что там происходит:)
Magsky
 
Posts: 3
Joined: Thu, 11 Oct 2007, 08:45

Postby SaMM » Tue, 16 Oct 2007, 18:44

Magsky wrote:Сейчас попробую авторизовать.
Твой вариант попробывал ругается именно на слово READ-BY-LINE.
Дальше не стал разбираться.
Очень был бы благодарен если бы ты написал пару комментариев в своем варианте,чтобы было легче разобраться,что там происходит:)

Слово READ-BY-LINE предложил VoidVolker.
Найди на форуме его определение, подключи его как плагин (лучше) или размести внутри <% ... %>

Code: Select all
#( test
NoActive
AsLoggedUser \ Авторизуемся
Action:
    READ-BY-LINE: "C:\file.txt"
        \ В цикле, оставляем на стеке строки файла
        \ Проверяем наличие в строке текущей даты, месяца, года
        2DUP S" *%DD%.%MM%.%YYYY%*" EVAL-SUBST WC-COMPARE IF
            MsgBox \ Если -1, выводим строку на экран
        ELSE
            2DROP \ Если 0, снимаем строку со стека
        THEN
    ;READ-BY-LINE
)#
SaMM
 
Posts: 236
Joined: Fri, 25 Aug 2006, 12:33

Postby elos » Fri, 19 Oct 2007, 10:23

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

Code: Select all
2007.10.10 01:00:13 Get TPLAK version: TPLAK - 2000K;Ver 8.2 01.05.22;ATSK;TEC ver 3.0;CPU Am186;#24100
2007.10.10 01:00:13 Get TPLAK date & time: 2007.10.10 01:00:13
2007.10.10 01:00:14 Set TPLAK date & time: Ok
2007.10.10 01:00:17 Get TPLAK date & time: 2007.10.11 01:00:17
...
2007.10.10 01:07:49 Get TPLAK version: TPLAK - 2000K;Ver 8.2 01.05.22;ATSK;TEC ver 3.0;CPU Am186;#24120
2007.10.10 01:07:49 Get TPLAK date & time: 2007.10.10 01:07:48
2007.10.10 01:07:50 Set TPLAK date & time: Ok
2007.10.10 01:07:53 Get TPLAK date & time: 2007.10.10 01:07:52



Решил использовать цикл READ-BY-LINE: / ;READ-BY-LINE - принцип как у AWK
А строки анализировать в CASE в зависимости от значения переменной line# -
не хотелось с IF связываться. Изменяя значение line# в ветке CASE -
изменяем regexp поиска...

в итоге "Ошибка стека в Action:" и где мусорю - не пойму

Code: Select all
SET path_lap_file="C:\nnCron\_code\LAP\2007101001.alm"
SET path_log_file="C:\nnCron\_code\LAP\xxxLAP_time_error.txt"

#( xxxLAPalert
\ NoActive
AsLoggedUser
WatchHotKey: "^+i"
1 VALUE line#   \ номер искомой строки
CREATE temp 256 ALLOT
CREATE RGXP1 256 ALLOT
CREATE RGXP2 256 ALLOT
CREATE RGXP3 256 ALLOT

Action:

READ-BY-LINE: "%path_lap_file%"
    2DUP    \ дублируем адрес строки для сохранения строки в буферах RGXP*                |--a u a u
    line#   \ какую строку ищем?                                                          |--a u a u n
    CASE
        1 OF S" /Get TPLAK version:/" RE-MATCH                                      \     |--a u flag
             IF 2 TO line#   \ будем искать строку с первым запрошенным временем          |--a u
                RGXP1 PLACE            \ сохранить строку в переменную RGXP1 на будущее   |--стек чист
             ELSE
                2DROP                  \ при несовпадении REGEXP - сбросить адрес строки со стека
             THEN
          ENDOF

        2 OF S" /Get TPLAK date & time:/" RE-MATCH                                  \     |--a u flag
             IF 3 TO line#  \ будем искать строку со вторым запрошенным временем          |--a u
                RGXP2 PLACE           \ сохранить строку в переменную RGXP1 на будущее    |--стек чист
             ELSE
                2DROP                 \ при несовпадении REGEXP - сбросить адрес строки со стека
             THEN
          ENDOF

    \ теперь самое интересное - сравнение двух времен - RGXP2 и RGXP3 _______________________________
    \ строки вроде бы одинаковые, но могут отличаться ДНЕМ, а не только временем...
    \
    \ 2007.10.10 01:00:13 Get TPLAK date & time: 2007.10.10 01:00:13  -->  RGXP2
    \ 2007.10.10 01:00:17 Get TPLAK date & time: 2007.10.11 01:00:17  ===  RGXP3
    \ надо вырезать                              ^^^^^^^^^^
    \                                           44        53 - 10 символов

        3 OF  S" /Get TPLAK date & time:/" RE-MATCH                                  \    |--a3 u3 flag
             IF 1 TO line#  \ опять будем искать строку с контроллером                    |--a3 u3
                RGXP3 PLACE
                RGXP2 COUNT 44 /STRING 10 MIN     \ a2 u2 вырезано время
                RGXP3 COUNT 44 /STRING 10 MIN     \ a3 u3 вырезано время
                COMPARE         \ нуль при совпадении - то есть FALSE
                IF                                                                 \ выводим все в лог!
                  RGXP1 COUNT S" %path_log_file%" LOG
                  RGXP2 COUNT S" %path_log_file%" LOG
                  RGXP3 COUNT S" %path_log_file%" LOG
                THEN
             ELSE
                2DROP                 \ при несовпадении REGEXP - сбросить адрес строки со стека
             THEN
          ENDOF

       DUP OF BEEP: 500 500 ENDOF
    ENDCASE
;READ-BY-LINE
)#
Last edited by elos on Mon, 22 Oct 2007, 15:30, edited 1 time in total.
elos
 
Posts: 667
Joined: Tue, 25 Apr 2006, 11:15

Postby elos » Fri, 19 Oct 2007, 10:26

Начал упрощать...

задача xxxLAPalert_if : работает
задача xxxLAPalert_case :
как только вставляю кусок кода 2 TO line# - ошибка стека, хотя на стеке то ничего не должно оставаться!

Code: Select all
SET path_lap_file="C:\nnCron\_code\LAP\2007101001.alm"
SET path_log_file="C:\nnCron\_code\LAP\xxxLAP_time_error.txt"

#( xxxLAPalert_if \ первое упрощение задачи
NoActive
AsLoggedUser
WatchHotKey: "^+i"
1 VALUE line#   \ номер искомой строки
CREATE temp 256 ALLOT
Action:
READ-BY-LINE: "%path_lap_file%"
2DUP    \ дублируем адрес строки для вывода в логе
temp PLACE
        S" /Get TPLAK version:/" RE-MATCH \ flag
IF
    LOG: "%path_log_file%" "%temp COUNT%"
    2 TO line# \ проверяю свое сомнение со стеком - все нормально
THEN
;READ-BY-LINE
)#

#( xxxLAPalert_case \ второе упрощение задачи
\ NoActive
AsLoggedUser
WatchHotKey: "^+i"
1 VALUE line#   \ номер искомой строки
CREATE temp 256 ALLOT
Action:
READ-BY-LINE: "%path_lap_file%"
    2DUP                                                  \ a u a u
    temp PLACE                                            \ a u
    line#                                                 \ a u n
    CASE
        1 OF                                              \ a u
            S" /Get TPLAK version:/" RE-MATCH             \ flag
            IF LOG: "%path_log_file%" "%temp COUNT%" THEN \ стек чист
\              2 TO line#                          \  чем мусорю на стек Action?
        ENDOF
\        DUP OF  ENDOF
    ENDCASE
;READ-BY-LINE
)#
elos
 
Posts: 667
Joined: Tue, 25 Apr 2006, 11:15

Postby elos » Fri, 19 Oct 2007, 12:08

поискал по форуму...

какой же окончательный вариант READ-BY-LINE: ?
и где он будет лежать (финальная версия), а то вещь пользительная, но ...

я использовал это
Code: Select all
: (READ-BY-LINE) { xt \ Lf Lc fEND -- }  ( a u xt -- )
    10240   \ максимальная длина строки (в символах)
    ALLOCATE THROW TO Lc
    R/O OPEN-FILE-SHARED THROW TO Lf
    BEGIN Lc 10238 Lf READ-LINE THROW WHILE
    Lc + 0 SWAP C!
    Lc ASCIIZ> xt EXECUTE \ TO fEND
    REPEAT  DROP
    Lf CLOSE-FILE DROP
    Lf FREE DROP
;

Пока склоняюсь к тому, что придется таки самому код ковырять с нуля. А в применение NONAME-конструкции так и не врубаюсь - кто бы просветил и навел, чтобы понять как работают :NONAME [NONAME NONAME]? то что в исходниках - не понимаю теми терминами, а в литературе встречал только про "неименованный код - для сокрытия смысла программы"
elos
 
Posts: 667
Joined: Tue, 25 Apr 2006, 11:15

Postby SaMM » Fri, 19 Oct 2007, 14:40

elos wrote:какой же окончательный вариант READ-BY-LINE: ?

Наверное, с самой позней датой публикации.
elos wrote:Пока склоняюсь к тому, что придется таки самому код ковырять с нуля

Зачем? :roll: Что тебе не нравится?
SaMM
 
Posts: 236
Joined: Fri, 25 Aug 2006, 12:33

Postby VoidVolker » Fri, 19 Oct 2007, 21:51

Code: Select all
какой же окончательный вариант READ-BY-LINE: ?

Code: Select all
: (?READ-BY-LINE) { xt \ Lf Lc fEND -- }  ( a u xt -- )
    -1 TO fEND
    10240   \ максимальная длина строки (в символах)
    ALLOCATE THROW TO Lc
    R/O OPEN-FILE-SHARED THROW TO Lf
    BEGIN Lc 10238 Lf READ-LINE THROW
    fEND AND WHILE  \ Выход по команде   
    Lc + 0 SWAP C!
    Lc ASCIIZ> xt EXECUTE TO fEND
    REPEAT  DROP
    Lf CLOSE-FILE DROP
    Lf FREE DROP
    Lc FREE DROP ;
: (READ-BY-LINE) { xt \ Lf Lc fEND -- }  ( a u xt -- )
    10240   \ максимальная длина строки (в символах)
    ALLOCATE THROW TO Lc
    R/O OPEN-FILE-SHARED THROW TO Lf
    BEGIN Lc 10238 Lf READ-LINE THROW WHILE
    Lc + 0 SWAP C!
    Lc ASCIIZ> xt EXECUTE \ TO fEND
    REPEAT  DROP
    Lf CLOSE-FILE DROP
    Lf FREE DROP
    Lc FREE DROP ;
: READ-BY-LINE \ compile: ( -- )
            \  execute: ( a u --)
    POSTPONE [NONAME
; IMMEDIATE
: ;READ-BY-LINE
    POSTPONE NONAME]
    POSTPONE (READ-BY-LINE)
; IMMEDIATE
: ;?READ-BY-LINE  ( ? -- )  \ 0 (FALSE) - выход из цикла, все остальные значения считаются правдой и цикл продолжится
    POSTPONE NONAME]
    POSTPONE (?READ-BY-LINE)
; IMMEDIATE
: READ-BY-LINE: eval-string,  POSTPONE READ-BY-LINE ; IMMEDIATE

Примеры:
Code: Select all
#( Test-Read-BY-Line
NoActive
Action:
\ Выведет в сообщении все строчки файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox
;READ-BY-LINE

S" D:\test.txt" READ-BY-LINE  \ Быстрее, т.к. строке не делается EVAL-SUBST (т.е. не работает %<...code...>%)
MsgBox
;READ-BY-LINE


\ Выведет в сообщении все строчки файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox -1
;?READ-BY-LINE

S" D:\test.txt" READ-BY-LINE  \ Быстрее, т.к. строке не делается EVAL-SUBST (т.е. не работает %<...code...>%)
MsgBox -1
;?READ-BY-LINE


\ Выведет в сообщении первую строчку файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox 0
;?READ-BY-LINE

S" D:\test.txt" READ-BY-LINE  \ Быстрее, т.к. строке не делается EVAL-SUBST (т.е. не работает %<...code...>%)
MsgBox 0
;?READ-BY-LINE
)#
95% вопросов уже обсуждались на форуме или ответы на них есть в мануале.        nnCron 1.93 b15.exe
Как правильно задавать вопросы.
User avatar
VoidVolker
Site Admin
 
Posts: 2898
Joined: Tue, 25 Apr 2006, 17:56

Postby elos » Tue, 23 Oct 2007, 12:02

Может кому и пригодится!

Таки нашел где "тормозил" - чисто автоматически считал - раз CASE, значить он "глотает" значение со стека, а внутри ветвей я могу работать со стеком дальше...
В FORTH значение на стеке для CASE будет там находиться пока его не снимет ENDCASE (сделает DROP, читаем стр. 101 GreenBook) - как-то не вдумывался и не было такого примера, как сложился у меня.
Пришлось использовать буфер для обработки строки в ветвях

Code: Select all
SET path_lap_file="C:\nnCron\_code\LAP\2007101001.alm"
SET path_log_file="C:\nnCron\_code\LAP\xxxLAP_time_error.txt"

#( xxxLAPalert
\ NoActive
AsLoggedUser
WatchHotKey: "^+i"
\ ______________________________________________________________________________________________
CREATE RGXP1 256 ALLOT
CREATE RGXP2 256 ALLOT
\ CREATE RGXP3 256 ALLOT
CREATE temp 256 ALLOT
1 VALUE line#   \ кол-во проверяемых совпадений
Action:

READ-BY-LINE: "%path_lap_file%"
temp PLACE  \ a u - работаем через буфер, так как внутри CASE нужна строка
            \ тянуться через лежащий на стеке line# - извращение...
line#   \ n - какую строку ищем? остается на стеке, пока ENDCASE не сделает  DROP
CASE
    1 OF temp COUNT S" /Get TPLAK version:/" RE-MATCH
         IF temp COUNT RGXP1 PLACE      2 TO line# THEN
      ENDOF

    2 OF temp COUNT S" /Get TPLAK date & time:/" RE-MATCH
         IF temp COUNT RGXP2 PLACE      3 TO line# THEN
      ENDOF

    3 OF temp COUNT S" /Get TPLAK date & time:/" RE-MATCH
         IF
            RGXP2 COUNT 43 /STRING 10 MIN     \ a2 u2 вырезано время
            temp COUNT  43 /STRING 10 MIN     \ a3 u3 вырезано время
            COMPARE         \ нуль при совпадении - то есть FALSE
            IF              \ не совпало - TRUE - выводим все в лог!
              LOG: "%path_log_file%" "%RGXP1 COUNT%"
              LOG: "%path_log_file%" "%RGXP2 COUNT%"
              LOG: "%path_log_file%" "%temp COUNT%" \ по сути это RGXP3
              LOG: "%path_log_file%" "                                           ^^^^^^^^^^"
            THEN
         1 TO line#
         THEN
      ENDOF
ENDCASE
;READ-BY-LINE
1 TO line# \ восстанавливаем номер первой искомой строки
)#
elos
 
Posts: 667
Joined: Tue, 25 Apr 2006, 11:15

Re: Поиск в txt файле и вывод строки с найденным совпадением

Postby ascerdfg1 » Fri, 27 Aug 2010, 18:43

Code: Select all
#( test_read_by_line1
NoActive
Action:
S" D:\test.txt" READ-BY-LINE
MsgBox -1
;READ-BY-LINE
)#
Пишет "внутрянняя ошибка"
nncron.exe v 1.93b10 Build 1141
tm.exe v 1.93b10 Build 569
Windows XP (5.1.2600) SP3
Комп без nnCron - груда металла!
User avatar
ascerdfg1
 
Posts: 541
Joined: Thu, 29 Nov 2007, 02:45
Location: г. Алексин

Re: Поиск в txt файле и вывод строки с найденным совпадением

Postby elos » Fri, 27 Aug 2010, 21:25

Примеры, поставлявшиеся со старой версией плагина:
Code: Select all
\ Выведет в сообщении все строчки файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox
;READ-BY-LINE

\ Выведет в сообщении все строчки файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox -1
;?READ-BY-LINE

\ Выведет в сообщении первую строчку файла test.txt
READ-BY-LINE: "D:\test.txt"
MsgBox 0
;?READ-BY-LINE
Видишь, в чём ошибся?
Code: Select all
Есть как просто построчное четение всего файла Код:
READ-BY-LINE: "file_name"
\...some_code...\
;READ-BY-LINE

так  и  условное  чтение  -  читает  следующую  строку только если на стеке
"правда", если 0 - то выйти из цикла.
READ-BY-LINE: "file_name"
\...some_code...\  \flag\
;?READ-BY-LINE
Если у тебя последняя "модульная" версия плагина, то там отсутствует ;?READ-BY-LINE
elos
 
Posts: 667
Joined: Tue, 25 Apr 2006, 11:15

Next

Return to nnCron forum (Russian)

Who is online

Users browsing this forum: No registered users and 1 guest