Показать полную графическую версию : [решено] Поиск повторяющихся слов в тексте при помощи StringRegExp
support23
26-02-2014, 12:53
Привет всем!
Возможно ли используя функцию StringRegExp определить наиболее часто повторяющееся слово в тексте?
Пример текста:
18.02.2014 15:58:13 user1
18.02.2014 17:30:58 user2
19.02.2014 12:54:34 user2
19.02.2014 13:14:28 user5
20.02.2014 14:59:43 user2
20.02.2014 16:31:05 user4
21.02.2014 11:47:27 user2
23.02.2014 12:21:25 user2
23.02.2014 10:35:14 user3
24.02.2014 13:50:20 user2
Слово для поиска - userX может содержать латинские буквы, цифры, символы "_" и "-"
Если через StringRegExp этого сделать нельзя, какой еще метод можно использовать?
p.s. желательно с примерами.
Заранее спасибо!
Проще всего — представлять текстовый файл как базу данных. Тогда можно, использовав, например, OLEDB с запросом вида «SELECT COUNT(Field3) AS TotalField3 GROUP Field3 ORDER BY TotalField3 DESC», определить наиболее часто встречающееся из «UserXX».
Как-то не дочитал:
p.s. желательно с примерами. »
AutoItSetOption("MustDeclareVars", 1)
Local Const $adOpenStatic = 3
Local Const $adLockOptimistic = 3
Local Const $adCmdText = 1
Local $sPathToSchema = "E:\Песочница\0365"
Local $sSourceFile = "0001.txt"
Local $oRecordSet = ObjCreate("ADODB.Recordset")
If Not FileExists($sPathToSchema & "\") Then
ConsoleWrite("Folder [" & $sPathToSchema & "] not found." & @CRLF)
Exit(1)
EndIf
If Not FileExists($sPathToSchema & "\" & $sSourceFile) Then
ConsoleWrite("Source file [" & $sSourceFile & "] not found." & @CRLF)
Exit(2)
EndIf
CreateSchema($sPathToSchema & "\Schema.ini", $sSourceFile)
$oRecordSet.Open( _
"SELECT TOP 1 [Name], COUNT(*) AS [Count] " & _
"FROM [" & $sSourceFile & "] " & _
"GROUP BY [Name] " & _
"ORDER BY COUNT(*) DESC", _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & $sPathToSchema & "';Extended Properties=""text;""", _
$adOpenStatic, $adLockOptimistic, $adCmdText _
)
ConsoleWrite("Name: " & $oRecordSet.Fields.Item("Name").Value & @CRLF)
ConsoleWrite("Count: " & $oRecordSet.Fields.Item("Count").Value & @CRLF)
$oRecordSet.Close
$oRecordSet = 0
RemoveSchema($sPathToSchema & "\Schema.ini")
Exit(0)
;=============================================================================
;=============================================================================
Func CreateSchema($sFullPathToSchemaIni, $sSourceFile)
If FileExists($sFullPathToSchemaIni) Then
FileDelete($sFullPathToSchemaIni)
EndIf
Local $hFile = FileOpen($sFullPathToSchemaIni, 2)
FileWriteLine($hFile, "[" & $sSourceFile & "]")
FileWriteLine($hFile, "ColNameHeader=False")
FileWriteLine($hFile, "Format=Delimited( )")
FileWriteLine($hFile, "TextDelimiter=none")
FileWriteLine($hFile, "DateTimeFormat=dd.mm.yyyy")
FileWriteLine($hFile, "CharacterSet=ANSI")
FileWriteLine($hFile, "Col1=Date date")
FileWriteLine($hFile, "Col2=Time char")
FileWriteLine($hFile, "Col3=Name char")
FileClose($hFile)
FileSetAttrib($sFullPathToSchemaIni, "+H")
EndFunc
;=============================================================================
;=============================================================================
Func RemoveSchema($sFullPathToSchemaIni)
If FileExists($sFullPathToSchemaIni) Then
FileDelete($sFullPathToSchemaIni)
EndIf
EndFunc
;=============================================================================
Результат:
Name: user2
Count: 6
P.S. Хорошо бы образец реального файла.
support23
27-02-2014, 13:06
Файл во вложении
При выполнении кода, на тексте для примера, указанного в первом сообщении, все работает
При выполнении кода с данным файлом получаю ошибку:
The requested action with this object has failed.:
$oRecordSet.Open( "SELECT TOP 1 [Name], COUNT(*) AS [Count] " & "FROM [" & $sSourceFile & "] " & "GROUP BY [Name] " & "ORDER BY COUNT(*) DESC", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & $sPathToSchema & "';Extended Properties=""text;""", $adOpenStatic, $adLockOptimistic, $adCmdText )
$oRecordSet.Open( "SELECT TOP 1 [Name], COUNT(*) AS [Count] " & "FROM [" & $sSourceFile & "] " & "GROUP BY [Name] " & "ORDER BY COUNT(*) DESC", "Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & $sPathToSchema & "';Extended Properties=""text;""", $adOpenStatic, $adLockOptimistic, $adCmdText )^ ERROR
support23, достаточно переименовать «auth_users.log» в «auth_users.txt».
support23
28-02-2014, 08:04
Все отлично работает, благодарю за решение !
madmasles
28-02-2014, 11:33
support23,
Мой вариант.#include (http://autoit-script.ru/autoit3_docs/keywords.htm##include) <Array.au3>
Local (http://www.autoitscript.com/autoit3/docs/keywords.htm#Local) $sFile = @ScriptDir (http://autoit-script.ru/autoit3_docs/macros.htm#@scriptdir) & '\auth_users.log', $aTmp, $iUb, $oDict, $iTmp, $aMax[2], $aRes[1], $aKey, $aItem
$aTmp = StringRegExp (http://autoit-script.ru/autoit3_docs/functions/StringRegExp.htm)(FileRead (http://autoit-script.ru/autoit3_docs/functions/FileRead.htm)($sFile), '(?<=:\d{2})\h{0,}([^\h]+?)[\n\r]', 3)
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) @error (http://autoit-script.ru/autoit3_docs/macros.htm#@error) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then) Exit (http://www.autoitscript.com/autoit3/docs/keywords.htm#Exit) 13
$iUb = UBound (http://autoit-script.ru/autoit3_docs/functions/UBound.htm)($aTmp)
$oDict = ObjCreate (http://autoit-script.ru/autoit3_docs/functions/ObjCreate.htm)('Scripting.Dictionary')
For (http://www.autoitscript.com/autoit3/docs/keywords.htm#For) $i = 0 To (http://www.autoitscript.com/autoit3/docs/keywords.htm#To) $iUb - 1
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $oDict.Exists($aTmp[$i]) Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
$iTmp = $oDict.Item($aTmp[$i]) + 1
$oDict.Item($aTmp[$i]) = $iTmp
If (http://www.autoitscript.com/autoit3/docs/keywords.htm#If) $aMax[1] < $iTmp Then (http://www.autoitscript.com/autoit3/docs/keywords.htm#Then)
$aMax[1] = $iTmp
$aMax[0] = $aTmp[$i]
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)
Else (http://www.autoitscript.com/autoit3/docs/keywords.htm#Else)
$oDict.Add($aTmp[$i], 1)
EndIf (http://www.autoitscript.com/autoit3/docs/keywords.htm#EndIf)
Next (http://www.autoitscript.com/autoit3/docs/keywords.htm#Next)
ConsoleWrite (http://autoit-script.ru/autoit3_docs/functions/ConsoleWrite.htm)('Max "' & $aMax[0] & '", count = ' & $aMax[1] & @LF (http://autoit-script.ru/autoit3_docs/macros.htm#@lf))
;~ бонус:
$iUb = $oDict.Count
ReDim (http://www.autoitscript.com/autoit3/docs/keywords.htm#ReDim) $aRes[$iUb + 1][2]
$aKey = $oDict.Keys
$aItem = $oDict.Items
$aRes[0][0] = $aMax[0]
$aRes[0][1] = $aMax[1]
For (http://www.autoitscript.com/autoit3/docs/keywords.htm#For) $i = 0 To (http://www.autoitscript.com/autoit3/docs/keywords.htm#To) $iUb - 1
$aRes[$i + 1][0] = $aKey[$i]
$aRes[$i + 1][1] = $aItem[$i]
Next (http://www.autoitscript.com/autoit3/docs/keywords.htm#Next)
$oDict = 0
$aTmp = 0
$aMax = 0
_ArrayDisplay (http://autoit-script.ru/autoit3_docs/libfunctions/_arraydisplay.htm)($aRes)
;~ в [0][0] массива: слово, всречающееся максимальное число раз
;~ в [0][1] массива: кол-во его вхождений
;~ в [1-n][0] массива: уникальные имена
;~ в [1-n][1] массива: кол-во их вхождений
support23
28-02-2014, 14:13
Спасибо, тоже отличное решение, особенно с учетом бонуса)
support23, если нужен такой же «бонус» в приведённом мною коде, замените:
$oRecordSet.Open( _
"SELECT TOP 1 [Name], COUNT(*) AS [Count] " & _
"FROM [" & $sSourceFile & "] " & _
"GROUP BY [Name] " & _
"ORDER BY COUNT(*) DESC", _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & $sPathToSchema & "';Extended Properties=""text;""", _
$adOpenStatic, $adLockOptimistic, $adCmdText _
)
ConsoleWrite("Name: " & $oRecordSet.Fields.Item("Name").Value & @CRLF)
ConsoleWrite("Count: " & $oRecordSet.Fields.Item("Count").Value & @CRLF)
на:
$oRecordSet.Open( _
"SELECT [Name], COUNT(*) AS [Count] " & _
"FROM [" & $sSourceFile & "] " & _
"GROUP BY [Name] " & _
"ORDER BY COUNT(*) DESC", _
"Provider=Microsoft.Jet.OLEDB.4.0;Data Source='" & $sPathToSchema & "';Extended Properties=""text;""", _
$adOpenStatic, $adLockOptimistic, $adCmdText _
)
While Not $oRecordSet.EOF
ConsoleWrite("Count: " & $oRecordSet.Fields.Item("Count").Value & @TAB & "Name: " & $oRecordSet.Fields.Item("Name").Value & @CRLF)
$oRecordSet.MoveNext()
WEnd
support23
28-02-2014, 17:28
support23, если нужен такой же «бонус» в приведённом мною коде, замените: »
Большое спасибо!
В обоих случаях получил функционал больше чем запрашивал изначально, Iska и madmasles вы очень помогли!
support23, посмотри мою Compare strings (http://azjio.ucoz.ru/load/vsjo_dlja_autoit3/skompilirovannye_skripty/compare_strings/4-1-0-65). Там есть в комбо - "Подсчёт уникальных строк", а в исходниках есть функция. Естественно даты нужно обрезать. Если используя рег.выр., то упрощённо обрезать указанное количество символов в начале каждой строки. Если нет так часто приходится делать, то в Notepad++ можно обрезать выделив столбиком, а оставшийся список обработать в "Compare strings".
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.
Available in ZeroNet 1osznRoVratMCN3bFoFpR2pSV5c9z6sTC