Что нового

Утилита для быстрого поиска-замены (в процессе разработки)

Suppir

Продвинутый
Сообщения
967
Репутация
62
Небольшая утилитка для выполнения быстрых замен текста внутри буфера обмена.

http://slil.ru/28260816

1. Запустите утилиту
2. Скопируйте какой-либо текст в буфер обмена (CTRL+c)
3. Нажмите CTRL+x. В трее должно появится сообщение в проделанной замене
4. Вставьте измененный текст куда вам нужно и посмотрите на результат
5. Для завершения работы утилиты нажмите CTRL+SHIFT+x

Утилита производит замены согласно настройкам в ini-файле (его можно дописывать, менять). Я хочу сделать следующую вещь - чтобы в ini можно было прописывать вспомогательные переменные, которые затем использовать в регулярных выражениях. А значит, необходимо текст из строки в ini-файле превратить в переменную внутри au3-скрипта. Не пойму, как это правильно сделать.



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

ЗЫ. Как присвоить переменной значение равное строке я знаю. Проблема в том, что нужно объявить переменную с заданным именем и значением, которые берутся из внешнего файла.
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

А почему это не подходит?

Код:
IniReadSection ( "filename", "section" )

Возвращает двумерный массив (например, $result[..][..]), в котором первая размерность (например, $result[n][0]) используется для ключа, а вторая (например, $result[n][1]) - для значения.

И далее:

Код:
Assign ( "varname", "data" [,flag] )


Вот примерчик на эту тему:
Код:
Dim $aArray
$aArray = IniReadSection ( "var's.ini", "var's" )

for $i = 1 to $aArray [0] [0]
	Assign ( $aArray [$i] [0], $aArray [$i] [1]  ,1 )
	MsgBox (0, "", $aArray [$i] [0] _  ; Имя переменной хранится в этом массиве
		& '=' _ 
		& Eval ($aArray [$i] [0]) )		   ; Значение извлекается по имени, т.е. если работает, значит переменная объявлена
Next

For $i = 1 to $aArray [0] [0]
	If IsDeclared ($aArray [$i] [0]) Then	; Здесь проверяется декларирование переменных 
		MsgBox (0,"", $aArray [$i] [0] & " is Declared!")
	EndIf
Next


var's.ini
Код:
[var's]
SomeVar1=001
SomeVar2=002
SomeVar3=003
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

Suppir [?]
нужно объявить переменную с заданным именем и значением, которые берутся из внешнего файла.
Код:
$aLine = StringSplit(FileReadLine("file.txt", 1), "=")
Assign($aLine[1], $aLine[2], 2)


первая строка в файле file.txt содержит:
INI:
MyVar=Value
Теперь будет создана переменная $MyVar со значением "Value".
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

CreatoR [?]
Теперь будет создана переменная $MyVar со значением "Value".

CreatoR, а как теперь эту переменную $MyVar вставить в StringRegExpReplace? Компилятор ругается - мол, нет такой переменной.


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

Заранее объявить мы ее не можем, так как нам неизвестно ее имя до чтения ini
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,673
Репутация
2,486
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

Suppir [?]
как теперь эту переменную $MyVar вставить в StringRegExpReplace? Компилятор ругается - мол, нет такой переменной.
Код:
$MyVar = Eval("MyVar")
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

Скачал, посмотрел... не так это делается, *.ini не так организовываются!

Примерно так:
Код:
[SectionName]
;Комментарий
VariableName=VariableValue

Все намного проще! Вот код:
Код:
HotKeySet("^x", "_Replace")
HotKeySet("^ч", "_Replace")
HotKeySet("^+x", "_Exit")
HotKeySet("^+ч", "_Exit")

if not FileExists("ToFindToReplace.ini") Then
	TrayTip ("AutoIt", "Не могу найти файл ""ToFindToReplace.ini""", 1)
	sleep(2000)
	TrayTip("clears any tray tip","",0)
	Exit
Else
	TrayTip ("AutoIt", "Скрипт запущен", 1)
	sleep(2000)
	TrayTip("clears any tray tip","",0)
EndIf

Func _Replace()
	Local $i, $Text, $aArrayVars = IniReadSection ( "ToFindToReplace.ini", "Variables" )
	$Text = ClipGet()
	if StringLen ( $Text ) <> 0 then
		for $i = 1 to $aArrayVars [0][0]
			$Text = StringRegExpReplace($Text, $aArrayVars [$i][0], $aArrayVars [$i][1])
		Next
	Else
		TrayTip ("AutoIt", "Буфер пуст!", 1)
	EndIf
	ClipPut($Text)
	TrayTip ("AutoIt", "Замена произведена", 1)
	sleep(1000)
	TrayTip("clears any tray tip","",0)
EndFunc


Func _Exit()
	TrayTip ("AutoIt", "Завершение работы скрипта", 1)
	Sleep(1000)
Exit
EndFunc

While 1	
WEnd


И ini тогда будет организован таким образом:
Код:
[Variables]

А=а
;ЧтоИскать=НаЧтоЗаменить
Б=б
В=в
;...

Кстати, ты забыл реализовать следующее: если буфер обмена пуст, то нужно вывести об этом уведомление ;)
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

killbond [?]
*.ini не так организовываются
Дело в том, что если организовывать ini стандартным способом, то AutoIt не сможет определить, где заканчивается Name и начинается Value (ведь регулярные выражения могут содержать знаки "=")

Кстати, ты забыл реализовать следующее: если буфер обмена пуст, то нужно вывести об этом уведомление
Спасибо, я сейчас делаю это; еще хочу сделать так, чтобы в случаях, когда замена идет долго, было уведомление, что скрипт работает (а не подвис)
 

killbond

Осваивающий
Сообщения
96
Репутация
32
Re: Как превратить строки из ini-файла в переменную AutoIt-скрипта?

Дело в том, что если организовывать ini стандартным способом, то AutoIt не сможет определить, где заканчивается Name и начинается Value (ведь регулярные выражения могут содержать знаки "=")

Это меняет дело... конечно, было бы удобнее использовать регулярные выражения без "=", но можно тогда сделать в качестве разделительного символа один или несколько тех, которые уж точно применяться в качестве регулярных выражений не будут ... тогда ini (только смысл называть его теперь файлом инициализации? :wacko:smile: совместит одновременно и удобство и простоту редактирования, а код станет короче и рациональней, примерно так:

Код:
#include <Array.au3>
#include <file.au3>

TraySetState ( 1 )
Opt("TrayMenuMode", 1)

$sDelimeter = "=(REPLACE)="								; Если не устраивает разделитель, просто сменить его здесь 
$sIniFile = @ScriptDir & "\" & "ToFindToReplace.ini"

HotKeySet("^x", "_Replace")
HotKeySet("^ч", "_Replace")
HotKeySet("^+x", "_Exit")
HotKeySet("^+ч", "_Exit")

$Edit = TrayCreateItem("Редактировать список замен")
$Exit = TrayCreateItem("Выход")

if not FileExists($sIniFile) Then
	TrayTip ("AutoIt", "Не могу найти файл " & $sIniFile, 1)
	sleep(2000)
	TrayTip("clears any tray tip","",0)
	Exit
Else
	TrayTip ("AutoIt", "Скрипт запущен", 1)
	sleep(2000)
	TrayTip("clears any tray tip","",0)
EndIf

Func _Replace()
	Local $i, $Text, $aArrayVars 
	
	if _SetTextToReplace ( $sIniFile ) = 0 Then												; Если функция возвратит 0, то вывести уведомление, что не найдены параметры замен
		TrayTip ("AutoIt", "Не найдены параметры замен в файле " & $sIniFile, 1)
		sleep(5000)
		TrayTip("clears any tray tip","",0)
		Return 0
	Else
		$aArrayVars = _SetTextToReplace ( $sIniFile )
	EndIf
	$Text = ClipGet()
	if StringLen ( $Text ) <> 0 then
		for $i = 0 to UBound ($aArrayVars, 1) - 1
			$Text = StringRegExpReplace($Text, $aArrayVars [$i][0], $aArrayVars [$i][1])
		Next
	Else
		TrayTip ("AutoIt", "Буфер пуст!", 1)
		sleep(1000)
		TrayTip("clears any tray tip","",0)
	EndIf
	ClipPut($Text)
	TrayTip ("AutoIt", "Замена произведена", 1)
	sleep(1000)
	TrayTip("clears any tray tip","",0)
EndFunc


Func _Exit()
	TrayTip ("AutoIt", "Завершение работы скрипта", 1)
	Sleep(1000)
Exit
EndFunc

Func _SetTextToReplace ( $sFile  )
	Local $iStringValue = _FileCountLines( $sFile ), _ 									; Кол-во строк в файле
	$aArray [$iStringValue] [2], _ 														; "Болванка" массива
	$aTempValue, _ 																		; Держит результат деления строки
	$iEmptyCounter = 0																	; Счетчик пустых строк, а также строк без разделителя (что позволяет оставлять комментарии и пустые строки)
	for $i = 1 to $iStringValue															; Сам цикл присвоения
		if StringLen ( FileReadLine ( $sFile, $i ) ) <> "" then 						; Если строка НЕ пуста, выполнить, иначе увеличить счетчик
			$aTempValue = StringSplit ( FileReadLine ( $sFile, $i ), $sDelimeter , 1 )	; Разделить строку, используя разделитель
			if UBound ( $aTempValue ) = 3 Then											; Если строка содержит разделитель выполнить, иначе увеличить счетчик
				$aArray [$i-(1+$iEmptyCounter)] [0] = $aTempValue [1]					; 0 элемент (что заменять)
				$aArray [$i-(1+$iEmptyCounter)] [1] = $aTempValue [2]					; 1 элемент (на что заменять)
			Else 
				$iEmptyCounter += 1
			EndIf
		Else
			$iEmptyCounter += 1
		EndIf		
	Next
	If ($iStringValue - $iEmptyCounter) = 0 Then										; Вернуть 0 если все строки пустые или комментарии
		Return 0
	EndIf
	ReDim $aArray [$iStringValue - $iEmptyCounter] [2]									; Переопределить массив, вычитая из него пустые строки и комментарии
	Return $aArray
EndFunc

While 1	
	Switch TrayGetMsg()
	Case $Edit
		ShellExecute ($sIniFile)
		TrayItemSetState ( $Edit, 4 )
	Case $Exit
		TrayItemSetState ( $Edit, 4 )
		_Exit()
	EndSwitch
WEnd


А "ini" тогда будет так организован:

Код:
А=(REPLACE)=а

Б=(REPLACE)=б

В=(REPLACE)=в

Что Найти=(REPLACE)=На Что Заменить

Хоть = искать=(REPLACE)=хоть "=" искать

Комментарий теперь можно так писать )))

Все просто и удобно :smile:

ЗЫ: извини за отсебятину в трее, но мне тоже показался этот скрипт полезным, поэтому я и приспособил под себя... возможно тебе это тоже покажется полезным, если файл с заменами можно будет вызвать из трея :smile:
 
Автор
S

Suppir

Продвинутый
Сообщения
967
Репутация
62
Re: Утилита для выполнения поиска-замен внутри буфера (в процессе разработки)

Новая версия утилиты:

(cобранная версия)
http://slil.ru/28279494


Код:
#include <UDF\GuiRichEdit.au3>
#include <GUIConstants.au3>

TraySetState ( 1 )
Opt("TrayMenuMode", 1)

HotKeySet("^x", "_Replace")
HotKeySet("^ч", "_Replace")
HotKeySet("^+x", "_Exit")
HotKeySet("^+ч", "_Exit")

Global $Records
Global $Search[1000][2]
Global $Matches
Global $i, $IN

$IniFile = @ScriptDir & "\" & "замена в буфере.ini"

$Edit = TrayCreateItem("Редактировать список замен")
$Exit = TrayCreateItem("Выход")

$Form1 = GUICreate("Form1", 800, 600, 300, 200)
$hRichEdit = _GUICtrlRichEdit_Create($Form1, "", 0, 0, 800, 600)
_GuiCtrlRichEdit_SetCtrlLimitOnText($hRichEdit, 99999999)

if not FileExists($IniFile) Then
	TrayTip ("AutoIt", "Не могу найти файл ""замена в буфере.ini""", 1)
	sleep(2000)
	TrayTip("clears any tray tip","",0)
	Exit
EndIf	

TrayTip ("AutoIt", "Скрипт запущен", 1)
sleep(2000)
TrayTip("clears any tray tip","",0)


While 1 
    Switch TrayGetMsg()
    Case $Edit
        ShellExecute ($IniFile)
        TrayItemSetState ( $Edit, 4 )
    Case $Exit
        TrayItemSetState ( $Edit, 4 )
        _Exit()
    EndSwitch
WEnd

Func _Replace()
	
	$in = FileOpen("замена в буфере.ini", 0)
	
	while 1
	
		local $i
		$line = FileReadLine($in)
		If @error = -1 Then ExitLoop
		
		$Matches = StringRegExp($line, "^Найти:(.+)", 1)	
		If @error = 0 Then
			$Search[$i][0] = $Matches[0] 
			ContinueLoop
		EndIf	
		
		$Matches = StringRegExp($line, "^Заменить на:(.+)", 1)
		If @error = 0 Then
			$Search[$i][1] = $Matches[0] 
			$i += 1
			ContinueLoop
		EndIf
		
wend

	if ClipGet() = "" Then 
		TrayTip ("AutoIt", "Буфер пустой!", 1)
		sleep(1000)
		TrayTip("clears any tray tip","",0)
	EndIf
	
	Local $i
	TrayTip ("AutoIt", "Произвожу замену...", 1)
	_GuiCtrlRichEdit_Paste($hRichEdit)
	$Text = _GUICtrlRichEdit_StreamToVar($hRichEdit)
	for $i = 0 to UBound($Search) - 1
		$Text = StringRegExpReplace($Text, $Search[$i][0], $Search[$i][1])
	Next
	_GuiCtrlRichEdit_SetText($hRichEdit, "")
    _GUICtrlRichEdit_StreamFromVar($hRichEdit, $Text)
	_GUICtrlRichEdit_SetSel($hRichEdit, 0, -1)
	_GuiCtrlRichEdit_Copy($hRichEdit)
	TrayTip ("AutoIt", "Замена произведена", 1)
	sleep(1000)
	TrayTip("clears any tray tip","",0)
		
EndFunc


Func _Exit()
	
	TrayTip ("AutoIt", "Завершение работы скрипта", 1)
	Sleep(1000)
	Exit
	
EndFunc



ini-файл должен выглядеть так:

Код:
Найти:а
Заменить на:! 

Найти: +
Заменить на:


Теперь утилита поддерживает:
- таблицы MS Word
- меню в трее с поддержкой быстрого редактирования ini-файла


Однако теперь наблюдается следующая проблема:
если в "найти и заменить" прописаны русские буквы, то замены не происходит. Скорее всего это связано с функцией _GUICtrlRichEdit_StreamToVar(), потому что когда я использовал функцию _GUICtrlRichEdit_GetCtrlText() замена работала нормально (но при этом разрушались таблицы word).



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

В общем, так:

если я использую
Код:
$Text = _GUICtrlRichEdit_StreamToVar($hRichEdit)

то не работает поиск-замена русских символов

если я использую
Код:
$Text = _GUICtrlRichEdit_GetCtrlText($hRichEdit)

то русские символы работают, но таблицы word разрушаются
 
Верх