Что нового

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

ynbIpb

Скриптер
Сообщения
398
Репутация
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 166
Репутация
2 331
Если нужно удалить дубликаты в файле, тогда вот:

Код:
$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')
 
Автор
Y

ynbIpb

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

CreatoR

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

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

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

ynbIpb

Скриптер
Сообщения
398
Репутация
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:
 
Автор
Y

ynbIpb

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