Что нового

Поиск строк в файле

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
Нужно проверить наличие нескольких строк в файле, если не одной из них там нет вывести сообщение. Как сделать эту проверку?
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Код:
$N = 5
Local $s[$N]; Number of relevant strings
$s[0] = 'string1'
$s[1] = 'string2'
$s[2] = 'string3'
$s[3] = 'string4'
$s[4] = 'string5'
$sPath = 'path to the file'; Path to the file
$hRead = FileOpen($sPath, 0)
$j = 0
While 1
	$line = FileReadLine($hRead); Read line from file one by one
	If @error = -1 Then ExitLoop; In EndOfFile Then Exit from cycle
	For $i = 0 to $N - 1
		If StringCompare($line, $s[$i]) = 0 Then $j = 1; Compare every relevant string with line
	Next
WEnd
If $j = 0 Then MsgBox(0, 'Result', 'There is no relevant strings in file')
 
Автор
A

Anton

Твори! Пусть завистники твои захлебываются пылью!
Сообщения
69
Репутация
3
Спасибо, то что надо.
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
298
Если уж делать FileOpen , то наверное надо и FileClose().
А вообще-то я давно заметил , что ф-я FileReadLine работает и без предварительного открытия файла ( FileOpen ) ,хотя в справке требуют открытия и закрытия ???
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
gregaz [?]
Если уж делать FileOpen , то наверное надо и FileClose().
необязательно, если в дальнейшем не будет использован хендл от открытого файла, то можно и не закрывать. после завершения скрипт сам отпустит этот хендл, то бишь закроет его.

А вообще-то я давно заметил , что ф-я FileReadLine работает и без предварительного открытия файла ( FileOpen )
работать то работает, только будет считывать каждый раз только первую строку. ибо при операциях с файлом через путь файл открывается, производится операция, а потом закрывается.
так можно делать в операциях типа FileRead. его не надо производить в цикле, файл откроется, содержимое перенесется в переменную потом закроется. дальше можно делать с ним то что надо.
но в данной задаче удобнее было именно в цикле читать построчно.
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
298
Kaster сказал(а):
работать то работает, только будет считывать каждый раз только первую строку.
Не согласен. Вот рабочий пример :
Код:
#Include <File.au3>
$sPatch='1.dat'
$iCount=_FileCountLines($sPatch)
Local $sText
For $i=1 To $iCount
	$sLine = FileReadLine($sPatch,$i)
	$sText &= $sLine
Next
MsgBox(0,'$sText',$sText)

Все строки прочитаны .
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
gregaz [?]
Не согласен. Вот рабочий пример :
таковым его назвать сложно.
для наглядности попробуй открыть файл размером в 100 мб скажем.
а дело тут вот в чем.
да, действительно, FileReadLine() при наличии номера строки считывает именно ту строку что надо. только что при этом он делает? он открывает файл, начинает считывать от начала нужное кол-во строк и при достижении предела выдает результат. другими словами, ты в своем скрипте открываешь и закрываешь файл столько раз сколько есть строк в твоем файле и каждый раз считываешь холостые строки предшествующие нужной. вместо того, чтобы считать все строки с самого начала. я думаю, неэффективность такого подхода очевидна.
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
298
Убедил вот этим :
Kaster сказал(а):
ты в своем скрипте открываешь и закрываешь файл столько раз сколько есть строк в твоем файле
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 165
Репутация
2 329
а зачем вообще построчно читать? если это небольшой файл, то можно его в переменную прочитать сразу, и потом обрабатывать её.


Добавлено:
Сообщение автоматически объединено:

Вот так:

Код:
$sCheck_Lines = 'string1|string2|string3|string4|string5'
$sCheck_Lines = '|' & $sCheck_Lines & '|'

$sPath = @ScriptDir & '\file.txt'; Path to the file
$aFile_Lines = StringSplit(StringStripCR(FileRead($sPath)), @LF)

$iLine_Found = 0

For $i = 1 To $aFile_Lines[0]
	If StringInStr($sCheck_Lines, '|' & $aFile_Lines[$i] & '|') Then
		$iLine_Found = 1
	EndIf
Next

If Not $iLine_Found Then MsgBox(0, 'Result', 'There is no relevant strings in file')



Добавлено:
Сообщение автоматически объединено:

Или с RegExp:

Код:
$sPath = @ScriptDir & '\file.txt'; Path to the file

$sCheck_Lines = 'string1|string2|string3|string4|string5'
$sCheck_Lines = StringRegExpReplace($sCheck_Lines, '([][{}().?+*\\^])', '\\\1')

$iRet = StringRegExp(FileRead($sPath), '(?im)^(' & $sCheck_Lines & ')(\r\n|\r|\n)?')

If Not $iRet Then MsgBox(0, 'Result', 'There is no relevant strings in file')
 

gregaz

AutoIT Гуру
Сообщения
1 166
Репутация
298
Весьма красивое решение : Использование массива строк в качестве элемента выбора в StringRegExpReplace
Похоже вместо :
Код:
$sCheck_Lines = StringRegExpReplace($sCheck_Lines, '([][{}()|.?+*\\^])', '\\\1')
$sCheck_Lines = StringReplace($sCheck_Lines, '\|', '|')

можно оставить :
Код:
$sCheck_Lines = StringRegExpReplace($sCheck_Lines, '([][{}().?+*\\^])', '\\\1')

Или здесь есть подводный камень ?
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 165
Репутация
2 329
gregaz [?]
Да, это я копипастил и при этом не подумал (а потому что спать нужно больше :smile: ), что символ «|» можно вовсе и не заменять.
 
Верх