Что нового

Как получить часть текста внутри строки с помощью рег. выражений

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Есть строка примерно следующего вида:

5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."

Как можно выцепить часть текста, находящегося между "\\" и "=(" (именно так, а не между "\" и "=")? Т.е. должно получиться следующее:

@C:\Windows\System32\FTM.exe,-6000

:smile:
 

kaster

Мой Аватар, он лучший самый
Команда форума
Глобальный модератор
Сообщения
4,020
Репутация
626
Yashied
ну и как обычно, что есть постоянная часть текста и что переменная? хотя про переменную более менее понятно что это
@C:\Windows\System32\FTM.exe,-6000
на вскидку
Код:
$s = '5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."'
$p = '.+\\\\(.+)=\(.+'
$a = StringRegExp($s, $p, 1)
MsgBox(0, '', $a[0])
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Или так (через Replace) :
Код:
$sPattern = '.*\\\\([^=]*?)=\(.*'
$sRezult = StringRegExpReplace ( $sText ,$sPattern,'\1',1 )
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Kaster сказал(а):
...что есть постоянная часть текста и что переменная?

***\\xxx=(nn)***

*** - произвольный текст любой длины
xxx - искомый текст любой длины
nn - число, длина может быть как один, так и два символа
красный цвет - постоянный текст

Вообщем, спасибо вам обоим, все работает!

:thumbs_up:

gregaz

.*\\\\([^=]*?)=\(.*

А почему именно "([^=]*?)", а не "(.+)", как у Kaster'а? В этом случае, если в искомом тексте попадется "=", то результат будет неверный.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Yashied [?]
***\\xxx=(nn)***
*** - произвольный текст любой длины
xxx - искомый текст любой длины
nn - число, длина может быть как один, так и два символа
красный цвет - постоянный текст

Это сужает параметры поиска, и соответственно добавляет надёжность замены :smile:

Код:
$vTest = '5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."'

$sPattern = '^.*\\{2}(.+(?==\(\d{1,2}\))).*$'
$sRet = StringRegExpReplace($vTest, $sPattern, '\1')

ConsoleWrite($sRet & @LF)


Тут получается строка до последнего =(nn), т.е даже если исходная строка будет такой:
5A\52C64B7E\\@C:\Windows=(1)\System32\FTM.exe,-6000=(1)"File Types..."
То всё равно вернётся полная строка до последнего =(1):
@C:\Windows=(1)\System32\FTM.exe,-6000
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Спасибо.

+1

CreatoR сказал(а):
Тут получается строка до последнего =(nn)...

А можно до первого?

И еще один вопрос. Для чего нужен "$" в конце шаблона. Без него тоже работает.
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
CreatoR сказал(а):
Это определяет конец строки, так вроде обработка выполняется быстрее.

А чем отличается от "\z"?
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
А почему именно "([^=]*?)", а не "(.+)", как у Kaster'а? В этом случае, если в искомом тексте попадется "=", то результат будет неверный.

Да конечно.
Для точного составления рег.выражения недостаточно
задания фрагмента текста:
Код:
5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."
В этом фрагменте в искомом тексте "=" отсутствует .

Точно так же для такой строки :
Код:
5A\52C64B7E\\@C:\Windows=(1)\System32\FTM.exe,-6000=(1)"File Types...=(22)
не будут работать и выражения от Kaster и CreatoR.

Ведь в тексте может где-то в конце встретиться фрагмент с : "=(" и приехали.

Нужно иметь весь текст, а не строчку. Чтобы учесть характерные особенности.
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
gregaz сказал(а):
Для точного составления рег.выражения недостаточно задания фрагмента текста...

Ясно. Спасибо.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
А вообще-то здесь лучше использовать "(.*?)" чем "(.+?)".
Ведь нужный текст между "стойками" может и отсутствовать.(или нужный текст будет в начале текста или в конце))
Или надо после выражения проверять @Extended.
 
Автор
Yashied

Yashied

Модератор
Команда форума
Глобальный модератор
Сообщения
5,379
Репутация
2,724
Остановился на следующем варианте:

Код:
$Text  = '5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."'

$Timer = TimerInit()
For $i = 1 To 10000
;	$sRet = StringTrimLeft(StringLeft($Text, StringInStr($Text, '=(') - 1), StringInStr($Text, '\\') + 1)
	$sRet = StringRegExpReplace($Text, '.*\\{2}(.+?(?==\(\d{1,2}\))).*', '\1')
Next

ConsoleWrite($sRet & @LF)
ConsoleWrite(TimerDiff($Timer) & @CR)


Но что интересно, рег. выражения в данном случае проигрывают String... функциям по скорости в ~1.5 раза.

:(
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
Yashied [?]
Но что интересно, рег. выражения в данном случае проигрывают String... функциям по скорости в ~1.5 раза.
Где-то на 30 %.
Да , кстати выражение от Kaster будет работать быстрее ,чем с StringRegExpReplace

И все же надо добавить
Код:
If @Extended=0 Then Return
:
иначе при не нахождении шаблона будет возвращен весь исходный текст
 

CreatoR

Must AutoIt!
Команда форума
Администратор
Сообщения
8,671
Репутация
2,481
gregaz [?]
Точно так же для такой строки :
...
не будут работать и выражения от Kaster и CreatoR.
Почему, мой код прекрасно это отрабатывает (если использовать .+?).

Ведь в тексте может где-то в конце встретиться фрагмент с : "=(" и приехали.
Для этого у меня и используется метод LookAhead, который ищёт всё что угодно до вхождения =(nn).

Yashied
[?]
А чем отличается от "\z"?
В данном случае ничем. Обычно \z это конец всей строки, т.е переменной, а $ конец одной отдельной строки в мультистроковом режиме ((?m)).

[?]
Остановился на следующем варианте
Так кажется быстрее:

Код:
$Text  = '5A\52C64B7E\\@C:\Windows\System32\FTM.exe,-6000=(1)"File Types..."'

$Timer = TimerInit()

For $i = 1 To 10000
	;$sRet = StringTrimLeft(StringLeft($Text, StringInStr($Text, '=(') - 1), StringInStr($Text, '\\') + 1)
	$sRet = StringRegExpReplace($Text, '^.*\\\\(.+?(?==\(\d\d?\))).*$', '\1')
Next

ConsoleWrite($sRet & @LF)
ConsoleWrite(TimerDiff($Timer) & @CR)


рег. выражения в данном случае проигрывают String... функциям по скорости в ~1.5 раза.
Я уже писал, что если это будет реализовано, то ситуация должна перевернуться.
 

gregaz

AutoIT Гуру
Сообщения
1,166
Репутация
299
CreatoR [?]
Почему, мой код прекрасно это отрабатывает (если использовать .+?).
Для выражения:
Код:
5A\52C64B7E\\@C:\Windows=(1)\System32\FTM.exe,-6000=(1)"File Types...(22)"
Он найдет до 1- скобки т.е.
Код:
@C:\Windows
 
Верх