Что нового

Как найти абсолютное совпадение строки?

agikon

Знающий
Сообщения
789
Репутация
17
Помогите пожалуйста решить данный вопрос.

Есть исходный текст, и есть искомый текст.
Найти надо именно абсолютное совпадение строки.
То есть если ищу "2", то если есть такая строка именно из одного символа "2" то только тогда счиается что есть совпадение.
А если например строка стостоит из "222" то совпадение не считается.

Я вот набросал скрипт, но он у меня ищет именно частичное совпадение, а не абсолютное построчное.


Код:
#include <GUIConstantsEx.au3>
#Include <WinAPIEx.au3>
#include <GUIEdit.au3>

$GUI = GUICreate("", 200, 150)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 70, 130, $ES_WANTRETURN)
$forma2 = GUICtrlCreateEdit("", 100, 10, 80, 20, $ES_WANTRETURN)
$button1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
$set = '22222' &@CRLF& '2222' &@CRLF& '22222' &@CRLF& '22222' &@CRLF& '2222' &@CRLF& '222' &@CRLF
$text10 = GUICtrlSetData($forma1, $set )
$text11 = GUICtrlSetData($forma2, '2' )

While 1
    Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
        Case $button1
				$text1 = GUICtrlRead($forma1)
				$text2 = GUICtrlRead($forma2)

				$array = StringRegExp($text1, $text2, 4, 1) ; вот тут надо как то переделать чтобы искало абсолютное совпадение строки
				If @error = 0 Then
					MsgBox(64,'','есть строка '&$text2&'', '')
				else
					MsgBox(64,'','нет абсолютного совпадения строки', '')
				endif
	EndSwitch
WEnd
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
вот так будет искать типа построчно
Код:
#include <GUIConstantsEx.au3>
#include <WinAPIEx.au3>
#include <GUIEdit.au3>
#include <array.au3>
$GUI = GUICreate("", 200, 150)
GUISetState(@SW_SHOW, $GUI)

$forma1 = GUICtrlCreateEdit("", 10, 10, 70, 130, $ES_WANTRETURN)
$forma2 = GUICtrlCreateEdit("", 100, 10, 80, 20, $ES_WANTRETURN)
$button1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
$set = '22222' & @CRLF & '2222' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF
$text10 = GUICtrlSetData($forma1, $set)
$text11 = GUICtrlSetData($forma2, '2')

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $button1
			$text1 = GUICtrlRead($forma1)
			$text2 = GUICtrlRead($forma2)
			$array = StringSplit(StringStripCR($text1), @LF)
			$search = _ArrayFindAll($array, $text2)
			If $search = -1 Then
				MsgBox(0, '', 'совпадений нет')
			Else
				MsgBox(0, '', 'найдено ' & UBound($search) & ' совпадений')
			EndIf
	EndSwitch
WEnd
если прямо в окне программы изменить строку на такую же, которую ищем получим в ответ количество совпадений.
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
agikon,
Может, примерно так?
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>

$hGUI = GUICreate('Test', 200, 150)
$nEdit1 = GUICtrlCreateEdit('22222' & @CRLF & '2222' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF, 10, 10, 70, 130, $ES_WANTRETURN)
$nEdit2 = GUICtrlCreateEdit('2', 100, 10, 80, 20, $ES_WANTRETURN)
$nButton1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton1
			$sText = GUICtrlRead($nEdit2)
			If StringRegExp(GUICtrlRead($nEdit1), '(?:^|\r\n)(\Q' & $sText & '\E)(?:\r\n|$)') Then
				MsgBox(64, '', 'есть строка ' & $sText, 0, $hGUI)
			Else
				MsgBox(64, '', 'нет абсолютного совпадения строки ' & $sText, 0, $hGUI)
			EndIf
	EndSwitch
WEnd
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
madmasles
Опровергающий скрипт. Наверно для конструкции \Q...\E нужно упоминать ограничения в использовании.
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>

$hGUI = GUICreate('Test', 200, 150)
$nEdit1 = GUICtrlCreateEdit('22222' & @CRLF & 'C:\Edit\2' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF, 10, 10, 70, 130, $ES_WANTRETURN)
$nEdit2 = GUICtrlCreateEdit('C:\Edit\2', 100, 10, 80, 20, $ES_WANTRETURN)
$nButton1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nButton1
            $sText = GUICtrlRead($nEdit2)
            If StringRegExp(GUICtrlRead($nEdit1), '(?:^|\r\n)(\Q' & $sText & '\E)(?:\r\n|$)') Then
                MsgBox(64, '', 'есть строка ' & $sText, 0, $hGUI)
            Else
                MsgBox(64, '', 'нет абсолютного совпадения строки ' & $sText, 0, $hGUI)
            EndIf
    EndSwitch
WEnd
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
AZJIO [?]
Опровергающий скрипт.
Может, тогда так?
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>

$hGUI = GUICreate('Test', 200, 150)
$nEdit1 = GUICtrlCreateEdit('22222' & @CRLF & 'C:\Edit\2' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF, 10, 10, 70, 130, $ES_WANTRETURN)
$nEdit2 = GUICtrlCreateEdit('C:\Edit\2', 100, 10, 80, 20, $ES_WANTRETURN)
$nButton1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nButton1
            $sText = GUICtrlRead($nEdit2)
            If StringInStr(@CRLF & GUICtrlRead($nEdit1) & @CRLF, @CRLF & $sText & @CRLF, 1) Then
                MsgBox(64, '', 'есть строка ' & $sText, 0, $hGUI)
            Else
                MsgBox(64, '', 'нет абсолютного совпадения строки ' & $sText, 0, $hGUI)
            EndIf
    EndSwitch
WEnd
Или так?
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>

Dim $aRet[1]

$hGUI = GUICreate('Test', 200, 150)
$nEdit1 = GUICtrlCreateEdit('22222' & @CRLF & 'C:\Edit\2' & @CRLF & '22222' & @CRLF & 'C:\Edit\2' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & _
		'222' & @CRLF & 'C:\Edit\2', 10, 10, 70, 130, $ES_WANTRETURN)
$nEdit2 = GUICtrlCreateEdit('C:\Edit\2', 100, 10, 80, 20, $ES_WANTRETURN)
$nButton1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $nButton1
			$sText = GUICtrlRead($nEdit2)
			$aText = StringSplit(StringStripCR(GUICtrlRead($nEdit1)), @LF)
			ReDim $aRet[$aText[0] + 1]
			For $i = 1 To $aText[0]
				If $aText[$i] == $sText Then
					$aRet[0] += 1
					$aRet[$aRet[0]] = $i
				EndIf
			Next
			If $aRet[0] Then
				$sText = 'есть строка(и) ' & $sText & @LF & 'Номер(а) строк(и): '
				For $i = 1 To $aRet[0]
					$sText &= $aRet[$i] & '; '
				Next
				MsgBox(64, '', StringTrimRight($sText, 2) & '.', 0, $hGUI)
			Else
				MsgBox(64, '', 'нет абсолютного совпадения строки ' & $sText, 0, $hGUI)
			EndIf
			$sText = ''
			$aText = 0
			ReDim $aRet[1]
			$aRet[0] = 0
	EndSwitch
WEnd


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

OffTopic:
AZJIO [?]
Наверно для конструкции \Q...\E нужно упоминать ограничения в использовании.
Не понимаю, почему эта конструкция не работает со строкой вида 'C:\Edit\2'. :stars:
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
А если извратиться так:
Код:
#include <GUIConstantsEx.au3>
#include <EditConstants.au3>

$hGUI = GUICreate('Test', 200, 150)
$nEdit1 = GUICtrlCreateEdit('22222' & @CRLF & 'C:\Edit\2' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF, 10, 10, 70, 130, $ES_WANTRETURN)
$nEdit2 = GUICtrlCreateEdit('C:\Edit\2', 100, 10, 80, 20, $ES_WANTRETURN)
$nButton1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
GUICtrlSetState(-1, $GUI_FOCUS)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $nButton1
		   $sText0=StringReplace(GUICtrlRead($nEdit1),"\E","\" & Chr (152)& "E" ) 
		   $sText = StringReplace(GUICtrlRead($nEdit2),"\E","\" & Chr (152)& "E" )
		 ; If StringRegExp($sText0, '(?:^|\r\n)(\Q' & $sText & '\E)(?:\r\n|$)') Then
               If StringRegExp($sText0, '(?m)^\Q' & $sText & '\E\r') Then	; Может даже так
                  MsgBox(64, '', 'есть строка ' & $sText, 0, $hGUI)
            Else
                MsgBox(64, '', 'нет абсолютного совпадения строки ' & $sText, 0, $hGUI)
            EndIf
    EndSwitch
WEnd



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

madmasles [?]
Не понимаю, почему эта конструкция не работает со строкой вида 'C:\Edit\2'.

Так в выражении : "\QC:\Edit\2\E" экранируется только "C:" :smile:
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
вариант, который я писал выше плюс указание номеров строк (подсмотрел в скрипте madmasles :smile: , правда весьма упростил )

Код:
#include <GUIConstantsEx.au3>
#include <GUIEdit.au3>
#include <array.au3>

$GUI = GUICreate("", 200, 150)
GUISetState(@SW_SHOW, $GUI)
$forma1 = GUICtrlCreateEdit("", 10, 10, 70, 130, $ES_WANTRETURN)
$forma2 = GUICtrlCreateEdit("", 100, 10, 80, 20, $ES_WANTRETURN)
$button1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
$set = '22222' & @CRLF & '2222' & @CRLF & '22222' & @CRLF & '22222' & @CRLF & '2222' & @CRLF & '222' & @CRLF
$text10 = GUICtrlSetData($forma1, $set)
$text11 = GUICtrlSetData($forma2, '2')

While 1
	Switch GUIGetMsg()
		Case $GUI_EVENT_CLOSE
			Exit
		Case $button1
			Local $text
			$text1 = GUICtrlRead($forma1)
			$text2 = GUICtrlRead($forma2)
			$array = StringSplit(StringStripCR($text1), @LF)
			$search = _ArrayFindAll($array, $text2)
			If $search = -1 Then
				MsgBox(0, '', 'совпадений нет')
			Else
				 For $i = 0 To UBound($search) - 1
                    $text &= $search[$i] & '; '
                Next
				MsgBox(0, '', 'найдено ' & UBound($search) & ' совпадений' & @CRLF & 'номера строк ' & $text)
			EndIf
	EndSwitch
WEnd

вопрос к знаток регулярных выражений - чем этот вариант хуже, чем с применением регулярного выражения... сам в них плохо разбираюсь. ну чтобы знать . можете пояснить?
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
madmasles
ну это да. я просто повелся на обычные цифры :smile:

тогда так
Код:
#include <GUIConstantsEx.au3>
#include <GUIEdit.au3>
#include <array.au3>

$GUI = GUICreate("", 200, 150)
GUISetState(@SW_SHOW, $GUI)
$forma1 = GUICtrlCreateEdit("", 10, 10, 70, 130, $ES_WANTRETURN)
$forma2 = GUICtrlCreateEdit("", 100, 10, 80, 20, $ES_WANTRETURN)
$button1 = GUICtrlCreateButton('искать', 100, 30, 80, 20)
$set = 'Adf' & @CRLF & 'sdf' & @CRLF & 'Adf' & @CRLF & '123' & @CRLF & 'Adf3' & @CRLF & 'adf' & @CRLF
$text10 = GUICtrlSetData($forma1, $set)
$text11 = GUICtrlSetData($forma2, 'Adf')

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            Exit
        Case $button1
            _search()
    EndSwitch
WEnd

Func _search()
    Local $text
    $text1 = GUICtrlRead($forma1)
    $text2 = GUICtrlRead($forma2)
    $array = StringSplit(StringStripCR($text1), @LF)
    $search = _ArrayFindAll($array, $text2, '', '', 1)
    If $search = -1 Then
        MsgBox(0, '', 'совпадений нет')
    Else
        For $i = 0 To UBound($search) - 1
            $text &= $search[$i] & '; '
        Next
        MsgBox(0, '', 'найдено ' & UBound($search) & ' совпадений' & @CRLF & 'номера строк ' & $text)
    EndIf
EndFunc   ;==>_search

конечно, поиск в массиве лучше уточнить из за возможности текста в разном регистре. плюс еще символ пробела. если в строке, которую мы ищем есть пробел, а в проверяемой строке его нет, то совпадений не будет. хотя визуально они будут одинаковы
ну и все ж что в сравнении с вариантом в котором используются регулярные выражения?
 

AZJIO

Меценат
Меценат
Сообщения
2,874
Репутация
1,194
madmasles
Более надёжный вариант - принудительно экранировать спецсимволы в шаблоне поиска.
Код:
$sText=StringRegExpReplace($sText, '[][{}()*+?.\\^$|=<>#]', '\\$0')


joiner
Он не лучше и не хуже, зависит от предпочтений. Требует включать UDF array.au3, по скорости - 2 вызова StringSplit и StringStripCR и _ArrayFindAll, которая сама по себе вызывает ещё кучу функций проверки входных пераметров.
регулярное выражение тратит время на компилицию поискового запроса ну или просто называем инициализация. Далее посимвольный поиск. В массиве тоже посимвольный поиск, но там ещё создаются указатели на элементы массива, и инициализация функций сравнения с каждым элементом. Вобщем это просто не нужно. Конкретно _ArrayFindAll в цикле вызывает _ArraySearch, а _ArraySearch вызывает очередные проверки валидности массива, ну и поиск продолжается даже если уже найдено.
В данном случае лучший вариант от madmasles, тупо проверка первого вхождения.
Код:
If StringInStr(@CRLF & GUICtrlRead($nEdit1) & @CRLF, @CRLF & $sText & @CRLF, 1) Then
 

joiner

Модератор
Локальный модератор
Сообщения
3,556
Репутация
628
ну я так и подозревал. :smile:
единственное, пробелы учитывать можно только с регулярным выражением? так как и моем и в варианте madmasles (в коротком) при добавлении пробела в искомый текст поиск оканчивается нулевым результатом
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
joiner [?]
в варианте madmasles (в коротком) при добавлении пробела в искомый текст поиск оканчивается нулевым результатом
Пример?
 
Автор
A

agikon

Знающий
Сообщения
789
Репутация
17
Спасибо за примеры.
Все варианты хороши, но так как требуется простенький поиск без подсчета количества совпадений то вот эта конструкция подходит
Код:
If StringInStr(@CRLF & GUICtrlRead($nEdit1) & @CRLF, @CRLF & $sText & @CRLF, 1) Then
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
joiner [?]
если в edit2 поставить после текста пробел
То не будет абсолютного совпадения строки, если такой строки (с пробелом) нет в edit1. Почему должно быть не так?
 
Верх