Автор Тема: StringRegExp , Поиск в файле фрагментов,содержащих специальные символы  (Прочитано 8211 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166
  • Репутация: 298
  • Пол: Мужской
    • Награды
Имеется файл данных ($sFileDat) , содержащий ряд строк вида:

'Menu='Ann|Aleks|Mishel|Maks\'
'Ann=c:\++Folder1\Folder2\Folder3\2.avi'
'Aleks=d:\Folder4\===Folder5\3.avi''
'Mishel=c:\++Folder1\Folder2\Folder3\4.avi'
'Maks=d:\Folder4\===Folder5\5.avi''
........=........................................

Требуется найти массив строк , начинающихся на заданную букву и  содержащих  заданный фрагмент .
Фрагмент может содержать в себе одну , несколько папок или весь путь (из правой части строки)
Как видим в фрагменте могут присутствовать специальные символы (+,|,\  и т.п.).
Я пытался делать так :
Код: AutoIt [Выделить]
$sReadFile = FileRead($sFileDat)
;$letter='a'
$letter='m'
;$folder=c:\++Folder1\Folder2\Folder3
$folder='d:\Folder4\===Folder5'
$folder=StringReplace ($folder,'\','\\')
$aFind=StringRegExp($txt, '(?i)(?m)(^'&$letter&'.*[=].*?\+'&$folder&'.*?)$', 3)
 

но не смог получить результата.


Самая большая проблема – её сформулировать. 

Русское сообщество AutoIt


Оффлайн beve [?]

  • Осваивающий
  • **
  • Сообщений: 104
  • Репутация: 30
  • Пол: Мужской
    • Награды
  • Версия AutoIt: 3.3.12.0
Если бы без StringRegExp(), то можно было так:
Код: AutoIt [Выделить]
 #include <file.au3>
Global $aRecords
Global $BeginLetter="M"
Global  $search="Folder"

If Not _FileReadToArray("file.Txt",$aRecords) Then
   MsgBox(4096,"Error", " Error reading log to Array     error:" & @error)
   Exit
EndIf

For $x = 1 to $aRecords[0]
    If StringLeft($aRecords[$x],2)="'"&$BeginLetter And StringInStr ( $aRecords[$x], $search,1) Then    Msgbox(0,'Line:' & $x, $aRecords[$x])
Next

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

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gregaz [?]
Цитировать
Требуется найти массив строк , начинающихся на заданную букву и  содержащих  заданный фрагмент .
Фрагмент может содержать в себе одну , несколько папок или весь путь (из правой части строки)
Как видим в фрагменте могут присутствовать специальные символы (+,|,\  и т.п.).
Код: AutoIt [Выделить]
#include <Array.au3>

$sReadFile = ClipGet() ;FileRead($sFileDat)
;$letter = 'a'
$letter = 'm'
;$folder = 'c:\++Folder1\Folder2\Folder3'
$folder = 'd:\Folder4\===Folder5'
$aFind = StringRegExp($sReadFile, '(?im)(^.?' & $letter & '.*=.*\Q' & $folder & '\E.*)[\n\r]?', 3)

_ArrayDisplay($aFind)


Так? :think:


Правила, Поиск, Супер тема


AutoIt is simple, subtle, elegant.


«Не оказываю тех. поддержку через ПМ/ICQ, и по электронной почте - для этого есть форум. (C)»
«Законы Мэрфи неоспоримы!»


Мои работы

Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
CreatoR  [?]
Цитировать
Так?
Спасибо . Почти так .
Строка  : Menu=Ann|Aleks|Mishel|Maks определяется как : Menu=Ann (до 1-го разделителя).

Для удобства тестирования я запишу исх.данные  в виде строковой переменной:
Код: AutoIt [Выделить]
$a='Menu=Ann|Aleks|Mishel|Maks'
$b='Ann=c:\++Folder1\Folder2\Folder3\2.avi'
$c='Aleks=d:\Folder4\===Folder5\3.avi'
$d='Mishel=c:\++Folder1\Folder2\Folder3\4.avi'
$e='Maks=d:\Folder4\===Folder5\5.avi'
$sString=$a & @crlf & $b & @crlf & $c & @crlf & $d & @crlf & $e
 

Кстати если можно в 2-х словах о метасимволах \Q и \E



Добавлено: Ноябрь 11, 2009, 15:03:06
Похоже именно \Q отменяет специальные значения символов до момента появления \E (еслит я правильно понимаю)
« Последнее редактирование: Ноябрь 11, 2009, 15:05:59 от gregaz, Причина: Объединение сообщений »

Русское сообщество AutoIt


Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gregaz [?]
Цитировать
Строка  : Menu=Ann|Aleks|Mishel|Maks определяется как : Menu=Ann (до 1-го разделителя).
Ну об этом небыло ни слова в задаче ;)
И что конкретно нужно искать в такой строке?

Цитировать
если можно в 2-х словах о метасимволах \Q и \E
Для строки попадающей между этими ключами отменяются спец. символы.

Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
Похоже неверно определяется по 1-й букве для случая :
Код: AutoIt [Выделить]
#include <Array.au3>

$a='Menu=Ann|Aleks|Mishel|Maks'
$b='Ann=c:\++Folder1\Folder2\Folder3\2.avi'
$c='Aleks=d:\Folder4\===Folder5\3.avi'
$d='Mishel=c:\++Folder1\Folder2\Folder3\4.avi'
$e='Maks=d:\Folder4\===Folder5\5.avi'
$sReadFile=$a & @crlf & $b & @crlf & $c & @crlf & $d & @crlf & $e

$letter = 'a'
$folder = 'd:\Folder4\===Folder5'
;$aFind = StringRegExp($sReadFile, '(?im)(^.?' & $letter & '.*=.*\Q' & $folder & '\E.*)[\n\r]?', 3)
;Может так :
$aFind = StringRegExp($sReadFile, '(?im)(^' & $letter & '.*=.*\Q' & $folder & '\E.*)[\n\r]?', 3)
_ArrayDisplay($aFind)
 



Добавлено: Ноябрь 11, 2009, 15:31:05

Ну об этом небыло ни слова в задаче И что конкретно нужно искать в такой строке?

Значит невнянто задал задание.
Искать также всю строку: 
если есть совпадение в правой части (после знака =) для Ann|Aleks|Mishel|Maks или Ann|Aleks
Если это сильно усложняет задачу может просто добавить исключение строки со словом : Menu


Добавлено: Ноябрь 11, 2009, 16:56:13
И еще как оказалось самое главное : Выражение не хочет работать на реальном файле ???
Одна из причин , оказывается флаг (?i) - флаг независимости от регистра написания работает только для латиницы и соответственно т,к, некоторые папки написаны на кирилице , то происходит неверное сравнение .
« Последнее редактирование: Ноябрь 11, 2009, 16:56:14 от gregaz, Причина: Объединение сообщений »

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gregaz [?]
Цитировать
Искать также всю строку:
Всё ровно не ясно, что в ней искать? Если фрагмент, то какой?

Цитировать
Одна из причин , оказывается флаг (?i) - флаг независимости от регистра написания работает только для латиницы  и соответственно т,к, некоторые папки написаны на кирилице , то происходит неверное сравнение .
Это проблема... но её можно решить так (лешившись сохранения структуры регистра букв в получаемых строках):
Код: AutoIt [Выделить]
#include <Array.au3>

$sReadFile = _
    'Menu=Ann|Aleks|Mishel|Maks' & @CRLF & _
    'Ann=c:\++Folder1\Folder2\Folder3\2.avi' & @CRLF & _
    'Aleks=d:\Folder Тест 4\===Folder5\3.avi' & @CRLF & _
    'Mishel=c:\++Folder1\Folder2\Folder3\4.avi' & @CRLF & _
    'Maks=d:\Folder4\===Folder5\5.avi'

$hFile = FileOpen(@DesktopDir & "\test.txt", 2)
FileWrite($hFile, $sReadFile)
FileClose($hFile)

$sReadFile = FileRead(@DesktopDir & "\test.txt")

$sLetter = 'a'
$sFragment = 'd:\Folder тест 4\===Folder5'

$aFind = StringRegExp(StringLower($sReadFile), '(?im)(^' & $sLetter & '.*=.*\Q' & StringLower($sFragment) & '\E.*)[\n\r]?', 3)
_ArrayDisplay($aFind)


Ну или можно так, ничего не нарушается, но это длиннее:
Код: AutoIt [Выделить]
#include <Array.au3>

$sReadFile = _
    'Menu=Ann|Aleks|Mishel|Maks' & @CRLF & _
    'Ann=c:\++Folder1\Folder2\Folder3\2.avi' & @CRLF & _
    'Aleks=d:\Folder тест 4\===Folder5\3.avi' & @CRLF & _
    'Mishel=c:\++Folder1\Folder2\Folder3\4.avi' & @CRLF & _
    'Maks=d:\Folder4\===Folder5\5.avi'

$hFile = FileOpen(@DesktopDir & "\test.txt", 2)
FileWrite($hFile, $sReadFile)
FileClose($hFile)

$sReadFile = FileRead(@DesktopDir & "\test.txt")
$sFragment = StringLower('d:\Folder тест 4\===Folder5')
$sLetter = 'a'

$aSplit_FRead = StringSplit(StringStripCR($sReadFile), @LF)
Dim $aFind[$aSplit_FRead[0]]

For $i = 1 To $aSplit_FRead[0]
    If StringRegExp(StringLower($aSplit_FRead[$i]), '(?im)(^' & $sLetter & '.*=.*\Q' & $sFragment & '\E.*)[\n\r]?') Then
        $aFind[0] += 1
        $aFind[$aFind[0]] = $aSplit_FRead[$i]
    EndIf
Next

ReDim $aFind[$aFind[0]+1]

_ArrayDisplay($aFind)
 


Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
CreatoR, огромное спасибо.
Последний вариант работает так как надо.  :IL_AutoIt_1:
Я эту задачу выполнял раньше используя ф-ию : _FileFindText + др.строковые ф-ии.
При большом файле поиск затягивался до 5-6 секунд.
Используя регулярное выражение операция выполняется почти на порядок быстрее.
Заодно пытаюсь изучить их.
Остался один вопрос ?
Всё ровно не ясно, что в ней искать? Если фрагмент, то какой?
Добавим в файл данных строку :
Ann|Aleks|Mishel|Maks=c:\++Folder1\Folder2\Folder3
При поиске фрагмента : c:\++Folder1\Folder2\Folder3 в массив попадает урезанная строка : Ann
Как исключить из полученного массива все строки , содержащие символ  '|' (можно ли без использования :  If StringInStr ...) ?



« Последнее редактирование: Ноябрь 15, 2009, 10:08:11 от gregaz »

Русское сообщество AutoIt


Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
Догадался таки :

Код: AutoIt [Выделить]
;...............................
;If StringRegExp(StringLower($aSplit_FRead[$i]), '(?im)(^' & $sLetter & '.*=.*\Q' & $sFragment & '\E.*)[\n\r]?') Then
If StringRegExp(StringRegExpReplace(StringLower($aSplit_FRead[$i]),'.*\|.*',''), '(?im)(^' & $sLetter & '.*=.*\Q' & $sFragment & '\E.*)[\n\r]?') Then
;..............................
 


Насколько корректно и оптимально оно ?

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gregaz [?]
Цитировать
При поиске фрагмента : c:\++Folder1\Folder2\Folder3 в массив попадает урезанная строка
На самом деле она не урезанная, это в списке урезается т.к каждая колонка разделяется символом |. Вот доказательсво этому (замени _ArrayDisplay на этот отрезок):

Код: AutoIt [Выделить]
$sRet = ""

For $i = 1 To $aFind[0]
    $sRet &= $aFind[$i] & @CRLF
Next

MsgBox(64, 'Title', $sRet)


Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
CreatoR  [?]
Цитировать
На самом деле она не урезанная, это в списке урезается т.к каждая колонка разделяется символом |.
Да это понятно.

Именно поэтому решил  исключить все строки с  символом | .
Код: AutoIt [Выделить]
;...............................

If StringRegExp(StringRegExpReplace(StringLower($aSplit_FRead[$i]),'.*\|.*',''), '(?im)(^' & $sLetter & '.*=.*\Q' & $sFragment & '\E.*)[\n\r]?') Then
;..............................
 

Насколько корректно и оптимально это ?

Оффлайн CreatoR [?]

  • Администратор
  • *
  • Сообщений: 7816
  • Репутация: 2284
  • Пол: Мужской
  • AutoIt is simple, subtle, elegant
    • CreatoR's Lab
    • Награды
  • Версия AutoIt: 3.3.10.2
gregaz [?]
Цитировать
Именно поэтому решил  исключить все строки с  символом |
Зачем?

Цитировать
Насколько корректно и оптимально это ?
Это будет учитываться при проверке, и зачем тогда замена? Я бы так сделал:

Код: AutoIt [Выделить]
For $i = 1 To $aSplit_FRead[0]
    $sLine = StringLower($aSplit_FRead[$i])
    $sPattern = '(?im)(^' & $sLetter & '.*=.*\Q' & $sFragment & '\E.*)[\n\r]?'
   
    If StringRegExp($sLine, $sPattern) And Not StringRegExp($sLine, '(?im)^.*\|.*?=') Then
        $aFind[0] += 1
        $aFind[$aFind[0]] = $aSplit_FRead[$i]
    EndIf
Next


Оффлайн gregaz [?]

  • AutoIt Гуру
  • *****
  • Сообщений: 1166

  • Автор темы
  • Репутация: 298
  • Пол: Мужской
    • Награды
CreatoR  [?]
Цитировать
Это будет учитываться при проверке, и зачем тогда замена? Я бы так сделал:

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

На конкретном примере все становится понятнее.
 

Русское сообщество AutoIt


 

Похожие темы

  Тема / Автор Ответов Последний ответ
11 Ответов
42279 Просмотров
Последний ответ Август 13, 2016, 16:38:36
от Alofa
24 Ответов
12186 Просмотров
Последний ответ Декабрь 05, 2009, 07:20:32
от SECTOR
24 Ответов
13302 Просмотров
Последний ответ Декабрь 10, 2009, 17:13:01
от gregaz
1 Ответов
2064 Просмотров
Последний ответ Август 04, 2012, 23:05:36
от inververs
0 Ответов
1358 Просмотров
Последний ответ Август 04, 2012, 22:59:17
от CreatoR
11 Ответов
2343 Просмотров
Последний ответ Июнь 03, 2015, 13:01:53
от Yashied
3 Ответов
2850 Просмотров
Последний ответ Сентябрь 11, 2015, 11:29:41
от Rjevsky
21 Ответов
3580 Просмотров
Последний ответ Апрель 08, 2016, 18:54:51
от man_without_face
0 Ответов
644 Просмотров
Последний ответ Октябрь 25, 2017, 01:39:27
от sh01u
2 Ответов
174 Просмотров
Последний ответ Февраль 09, 2018, 21:22:53
от Vanches