Что нового

[RegExp] Разбиение строки на элементы, с условием

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Есть строка примерно такого вида:

Код:
'_00:00#GG##10000#77#--#5000#-10#--#fff#_00:00#HH##5000#60#.1#--#6.5#--#5hj#_00:00#LL##30000#700#6.9#--#6.7#--109#_00:00#JJ##5000#jghj#5.2#5.0#5.6#54.8#600#_00:00#DD##90000#498#14#1.3#1.3#--#5ko#_'

Необходимо получить из нее массив, деление на элементы должно происходить по символу "_"
Хватило бы обычного StringSplit, но в данном случае необходимо брать только те элементы, которые содержат подстроки GG и LL (эти подстроки могут меняться, но их всегда несколько, вроде как "белый список"), т.е. массив должен содержать:

Код:
00:00#GG##10000#77#--#5000#-10#--#fff#
00:00#LL##30000#700#6.9#--#6.7#--109#

Конечно, можно после StringSplit прогнать цикл и удалить ненужное, но, думаю, в StringRegExp можно создать подходящий паттерн, делающий все за одно действие - но у меня не хватает опыта работы с регулярными выражениями(
 

madmasles

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

$sTxt = '_00:00#GG##10000#77#--#5000#-10#--#fff#_00:00#HH##5000#60#.1#--#6.5#--#5hj#_00:00#LL##30000#700#6.9#--#6.7#--109#_00:00#JJ##5000#jghj#5.2#5.0#5.6#54.8#600#_00:00#DD##90000#498#14#1.3#1.3#--#5ko#_'

$aTxt = StringRegExp($sTxt, '_(.+?(?:GG|LL).+?)_', 3)
_ArrayDisplay($aTxt)
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
Ещё:
Код:
$aTxt = StringRegExp($sTxt, '(\d{2}:\d{2}#[GG|LL].*?)_', 3)

Код:
$aTxt = StringRegExp($sTxt, '_(.*?[GG|LL].*?)_', 3)
 

sngr

AutoIT Гуру
Сообщения
1,010
Репутация
408
Код:
#include 'array.au3'
$a='_00:00#GG##10000#77#--#5000#-10#--#fff#_00:00#GG##5000#60#.1#--#6.5#--#5hj#_00:00#LL##30000#700#6.9#--#6.7#--109#_00:00#JJ##5000#jghj#5.2#5.0#5.6#54.8#600#_00:00#DD##90000#498#14#1.3#1.3#--#5ko#_'
$str=StringRegExp($a,'[^_]*[GL]{2}[^_]*',3)
_ArrayDisplay($str)
 

madmasles

Модератор
Глобальный модератор
Сообщения
7,790
Репутация
2,322
Zaramot, sngr,
У Вас будут входить строки с GL и с LG.
 

Zaramot

I ♥ AutoIt
Сообщения
1,160
Репутация
660
madmasles,
У вас тоже...
Код:
#include <Array.au3>

$sTxt = '_00:00#GL##20000#77#--#2000#-22#--#fff#_00:00#GG##10000#77#--#5000#-10#--#fff#_00:00#HH##5000#60#.1#--#6.5#--#5hj#_00:00#LL##30000#700#6.9#--#6.7#--109#_00:00#JJ##5000#jghj#5.2#5.0#5.6#54.8#600#_00:00#DD##90000#498#14#1.3#1.3#--#5ko#_'

$aTxt = StringRegExp($sTxt, '_(.+?(?:GG|LL).+?)_', 3)
_ArrayDisplay($aTxt)


Добавленно:
Код:
_00:00#GL##20000#77#--#2000#-22#--#fff#
 

madmasles

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

$sTxt = '_00:00#GL##20000#77#--#2000#-22#--#fff#_00:00#GG##10000#77#--#5000#-10#--#fff#_00:00#HH##5000#60#.1#--#6.5#--#5hj#_00:00#LL##30000#700#6.9#--#6.7#--109#_00:00#JJ##5000#jghj#5.2#5.0#5.6#54.8#600#_00:00#DD##90000#498#14#1.3#1.3#--#5ko#_'
$aTxt = StringRegExp($sTxt,'[^_]+(?:GG|LL)[^_]+',3)
;~ $aTxt = StringRegExp($sTxt, '(\d{2}:\d{2}#[GG|LL].*?)_', 3)
;~ $aTxt = StringRegExp($sTxt, '_([^_]+(?:GG|LL)[^_]+)_', 3)
_ArrayDisplay($aTxt)
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
madmasles
Можно немного улучшить, добавив ? после +
Код:
[^_]+?(?:GG|LL)[^_]+
Т.к GL или LL идет ближе к левой части строки, то "ленивый" захват будет быстрее и уберет лишние откаты.


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

Я бы делал так
Код:
_([^_]+?(?:GG|LL)[^_]+)
т.к точно известно что искомая группа начинается всегда с _ тем самым удаляя ненужные проверки остальной части выражения, если текущий символ не _
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
inververs
Символ _ ничего не решает. При начале поиска он в любом случае будет проверять каждую букву, пока не встретит _, после которой частичные совпадения сбрасываются и начинается новое сравнение.
 

inververs

AutoIT Гуру
Сообщения
2,135
Репутация
465
AZJIO
Про какой паттерн вы говорите? Если взять например такой
Код:
[^_]+?(?:GG|LL)[^_]+
и строку которая не подходит
_00:00#HH##5000#60#.1#--#6.5#--#5hj#
то что бы это понять, будет выполненно очень много вычислений для каждого символа в этой строке, а если паттерн поменять, добавив проверку на _
Код:
_([^_]+?(?:GG|LL)[^_]+)
то вычисления будут только для первого т.к первый символ в ней это _
 
Автор
W

WSWR

AutoIT Гуру
Сообщения
941
Репутация
363
Всем спасибо за интересные примеры
Пригодятся как в этом случае, так и на будущее
 

AZJIO

Меценат
Меценат
Сообщения
2,879
Репутация
1,194
inververs
На практике показало что быстрее, но это одно из случайных совпадений, потому что объяснение не доказывает что это должно быть быстрее. Я понимаю что вы хотите сказать, но так же я понимаю, что всё регулярное выражение является цепью равноценных символов, и какой то отдельный символ не является ускоряющим. Данный паттерн не содержит внутри себя допустимых символов "_", а значит будет сброс при встрече этого символа, и не обязательно зацепившись за этот символ как за якорь регулярное выражение не будет ничего проверять, оно так же будет всё проверять каждый символ, как и раньше. Хотя много рекурсивных и других ветвлений, которые заставляют возвращаться назад замедляют выполнение. Но правила точного нет, я сколько раз убеждался, что интуиция в плане регулярного выражения обманчива, и пока не проверишь с секундомером, никаких предположений можно не строить.
 
Верх