Что нового

Как удалить дубликаты строк в файле

ynbIpb

Скриптер
Сообщения
399
Репутация
109
У меня тут тоже вопрос по поводу поиска в тексте:
Я с помощью StringRegExp нахожу в HTML файле некий текст и формирую список txt. Но часто встречаются дубликаты, как бы их поудалять?
Код:
$page = FileOpen (@ScriptDir & "\pages\01.htm", 0)
$page_read = FileRead ($page)
FileClose ($page)
$nOffset = 1
$allnames = ""
While 1
$Names = StringRegExp ($page_read, "Автор: <b>(.*?)</b>" , 1, $nOffset)
If @error = 0 Then
        $nOffset = @extended
    Else
        ExitLoop
EndIf
$allnames &= $Names[0]&@CRLF
WEnd
msgbox(0, "", $allnames)
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 567
Репутация
2 434
Если нужно удалить дубликаты в файле, тогда вот:

Код:
$sFileName = "Test.txt"
$sFilePath = @ScriptDir & "\"
$sFile = $sFilePath & $sFileName

$iRet = _FileDeleteDuplicateLines($sFile, 0)
$iExtended = @extended

If $iRet = 1 And $iExtended > 0 Then
	MsgBox(64, "Results", StringFormat("В файле <%s> удалено дублирующихся строк: %i", $sFileName, $iExtended))
ElseIf $iExtended = 0 Then
	MsgBox(64, "Results", StringFormat("В файле <%s> нет дублирующихся строк.", $sFileName))
ElseIf @error = 1 Then
	MsgBox(48, "Ошибка", StringFormat("Файл <%s> не найден.", $sFileName))
ElseIf @error = 2 Then
	MsgBox(48, "Ошибка", StringFormat("Ошибка при попытке записи в Файл <%s>.", $sFileName))
EndIf

Func _FileDeleteDuplicateLines($sFile, $iCaseSense=0)
	If Not FileExists($sFile) Then Return SetError(1)
	Local $sFRead = FileRead($sFile)
	Local $aFSplit = StringSplit(StringStripCR($sFRead), @LF)
	Local $sFileContent = "", $iExtended = 0, $sLastChars = StringRight($sFRead, 2)
	
	;Проходим весь массив, и проверяем каждую строку
	For $i = 1 To $aFSplit[0]
		If $aFSplit[$i] = "" Then ContinueLoop
		
		;Тут делаем проверку в переменной, в которую скапливаются строки (не дублирующиеся)
		If Not StringInStr($sFileContent, $aFSplit[$i] & @CRLF, $iCaseSense) Then
			$sFileContent &= $aFSplit[$i] & @CRLF
		Else
			$iExtended += 1
		EndIf
	Next
	
	If $sLastChars <> @CRLF Then $sFileContent = StringTrimRight($sFileContent, 2)
	
	;Пишем в файл уже без дублей
	Local $hFOpen = FileOpen($sFile, 2)
	If $hFOpen = -1 Then Return SetError(2)
	
	FileWrite($hFOpen, $sFileContent)
	FileClose($hFOpen)
	
	Return SetExtended($iExtended, 1)
EndFunc



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

А если просто в строке удалить, то можно так:

Код:
$allnames = StringRegExpReplace($allnames, '(?sm)(^[^\n]+\n?)(.*?)^\1', '\1\2')
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Спасибо, вроде смысл первого понял.
а вот со вторым вариантом недогоняю.
оно только в строке удаляет дубли? тоесть должен быть какойто разделитель?
вот так попробовал ничего:
Код:
$allnames = "раз раз два" 
$allnames = StringRegExpReplace($allnames, '(?sm)(^[^\n]+\n?)(.*?)^\1', '\1\2')
MsgBox (0, "", $allnames)
Если не затруднит, то поподробней, что каждый символ в шаблоне выпоняет.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8 567
Репутация
2 434
ynbIpb [?]
оно только в строке удаляет дубли? тоесть должен быть какойто разделитель?
Удаляет дубликаты строк, да, разделитель это новая строка (@CRLF).

вот так попробовал ничего
Для одной строки можно так:
Код:
$allnames = "one one two"
$allnames = StringRegExpReplace($allnames, '\s?(\b\S+\b)(?=.*\b\1\b)', '')
ConsoleWrite(@extended & @CRLF)
MsgBox (0, "", $allnames)

Хотя для не латинских симолов оно почему то не срабатывает...
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Вот теперь работает.
Код:
$allnames = "раз"&@CRLF&"раз"&@CRLF&"два"
$allnames = StringRegExpReplace($allnames, '(?sm)(^[^\n]+\n?)(.*?)^\1', '\1\2')
MsgBox (0, "", $allnames)

Но! мне хочется понять принцип действия. у меня туго с регекспами, сколько не перечитывал справку.
Если не трудно то словами можно описать порядок происходящих действия в этом выражении, что конкретно в данной ситуации выполняет каждый символ?
 

snoitaleR

AutoIT Гуру
Сообщения
854
Репутация
223
ynbIpb
Вот он - повод для меня начать изучение регулярных выражений... :smile:
Открыл я "regexp2-ref.pdf" и бегло просмотрел его...
Понял одну простую вещь: чтобы понять логику регулярного выражения надо до автоматизма "зазубрить" значение каждого метасимвола, чтобы при разборе каждого символа в выражении не заглядывать в справочник, иначе теряется основная мысль...
Продолжаем изучать дальше... :smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4 020
Репутация
622
Да. Читаешь слева направо. Каждый символ как правило сам себя и обозначает, помимо специальных.
Встретил слеш (\) значит следующий за ним спецсимвол читает as is, встретил скобки без слешов, значит то, что внутри них единый объект. Ну и да, спецсимволы надо выучить :smile:
 
Автор
ynbIpb

ynbIpb

Скриптер
Сообщения
399
Репутация
109
Ну хорошо. бум курить справку дальше. тему отметил как решённую. всем спасибо за участие.
 

Norm

Знающий
Сообщения
104
Репутация
12
Поиск дубликатов СТРОК в тексте с помощью превращения его в массив работает очень медленно,
поэтому для этого я использую вот эту регулярку:
Код:
StringRegExpReplace($sString,  "(?ms)^(\V+\R*)^(?=.*\1)" , "")
 
Последнее редактирование:
Верх