1

Тема: AHK: Поиск в буфере обмена по нескольким регекспам

Здравствуйте!
Задача: поиск совпадений в буфере обмена по группе регулярных выражений. Одна из подзадач — поиск позиции и длины совпадения. Решил объединить регулярки в одну через знак альтернативы. Для большей читаемости поместил их в переменные.

r01 = (^\s+) ; Начальные пробелы.
r02 = (\s+$) ; Конечные пробелы.
r03 = (\s{2,}) ; Несколько пробелов подряд.
; Таких переменных может быть и около сотни.
FoundPos := RegExMatch(clipboard, "P)(" r01 "|" r02 "|" r03 ")", LastLine)
MsgBox Позиция %FoundPos%`nДлина совпадения %LastLine%.

Так работает. Можно добавлять или наоборот удалять шаблоны. Но хотелось бы при совпадении получить данные о том, какой из шаблонов нашел совпадение. Это бы позволило править шаблоны при ложных срабатываниях или вывести сообщение-комментарий и т. д. Возможно ли это вообще средствами Autohotkey?

2

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Если известна позиция, а она известна, то можно вычислить сработавший шаблон по этому признаку. Например, если "FoundPos" равен единице — сработал первый шаблон, иначе если "FoundPos" плюс "LastLine" равно длине строки — сработал второй шаблон, а если не то и не другое, то — третий.

Ещё можно поместить шаблоны в массив и в цикле передавать их по очереди, пока "FoundPos" не отличается от нуля, тогда, сработавший шаблон вычисляется по текущему индексу цикла.

3

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Так вряд ли получится, подшаблоны не идут в тексте один за другим (использован знак |).

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

4

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Поясните пожалуйста. Я понял ситуацию так:

str1 := "text  text"
str2 := " text"
str3 := "text "
	
r01 = (^\s+) ; Начальные пробелы.
r02 = (\s+$) ; Конечные пробелы.
r03 = (\s{2,}) ; Несколько пробелов подряд.

Loop 3 {
	current_str := str%A_Index%
	; Таких переменных может быть и около сотни.
	FoundPos := RegExMatch(current_str, "P)(" r01 "|" r02 "|" r03 ")", LastLine)
	MsgBox Позиция %FoundPos%`nДлина совпадения %LastLine%.
	
	if (FoundPos == 1)
		MsgBox, В строке - '%current_str%'`nШаблон №1 - '%r01%'
	else if (FoundPos + LastLine - 1 == StrLen(current_str))
		MsgBox, В строке - '%current_str%'`nШаблон №2 - '%r02%'
	else if (FoundPos)
		MsgBox, В строке - '%current_str%'`nШаблон №3 - '%r03%'
	else
		MsgBox, В строке - '%current_str%'`nНичего не найдено
	
	For i, reg_ex in [r01, r02, r03] {
		if (FoundPos := RegExMatch(current_str, "P)(" reg_ex ")", LastLine)) {
			MsgBox,% Format("В строке - '{}'`nШаблон №{} - '{}'", current_str, i, reg_ex)
		}
	}
}

5

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Не учли:

stokber пишет:

Таких переменных может быть и около сотни.

Как узнать, какой подшаблон сработал здесь:

str := "ab"
r1 := "(cd)"
r2 := "(ab)"

FoundPos := RegExMatch(str, "P)(" r1 "|" r2 ")", m)
MsgBox, % FoundPos "`n" m

?

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

6

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Очевидно — "r2". Разве нет?

str := "ab"
r1 := "(cd)"
r2 := "(ab)"

For i, reg_ex in [r1, r2] {
	if (FoundPos := RegExMatch(str, "P)(" reg_ex ")", LastLine)) {
		MsgBox,% Format("В строке - '{}'`nШаблон №{} - '{}'", str, i, reg_ex)
	}
}

7 (изменено: teadrinker, 2020-04-29 15:26:25)

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Так-то да, но вы изменили условие задачи. Понятно, что если подставлять эти подшаблоны по очереди, в конце концов один подойдёт (или никакой не подойдёт). Но шаблон должен выглядеть так: r1 "|" r2, в этой задаче нужно применить RegEx один раз.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

8

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Возможно, Вы правы, но на мой взгляд, автор обозначил это решение как подход, которым он воспользовался, а задача в том, чтобы помимо нахождения позиции и длины совпадения, обозначить так же шаблон, который сработал.

Но, если автору принципиально совершать всего один вызов, то мне эта принципиальность не понятна, от чего я этим подходом и не руководствовался.

9

Re: AHK: Поиск в буфере обмена по нескольким регекспам

KusochekDobra пишет:

если автору принципиально совершать всего один вызов, то мне эта принципиальность не понятна

Ну, представьте, что текст очень большой, подумайте о производительности.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

10

Re: AHK: Поиск в буфере обмена по нескольким регекспам

str := "ab"
r1 := "(cd)"
r2 := "(ab)"

RegExMatch(str, r1 "|" r2, m)
if (m1 = "") 
   MsgBox, % m2

11 (изменено: teadrinker, 2020-04-29 22:39:43)

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Да, очевидное решение — проверить подшаблоны на пустоту, хотя я бы это по-другому записал:

str := "ab"
r1 := "(cd)"
r2 := "(ab)"

RegExMatch(str, r1 "|" r2, m)
Loop
   i := A_Index
until m%i% != "" && found := true

MsgBox, % found ? i : ""

Есть ещё вариант — промаркировать подшаблоны:

str := "ab"
r1 := "((*:1)cd)"
r2 := "((*:2)ab)"

RegExMatch(str, "O)" r1 "|" r2, m)
MsgBox, % m.Mark
Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

12

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Спасибо всем откликнувшимся. Обсуждение ушло немного как бы вширь. Мне, как пользовавшемуся в AHK большей частью эмуляцией клавиатуры нужно некоторое время для переваривания. Извиняюсь, что не внес сразу ясность в назначение скрипта. Попробую объяснить общий алгоритм. Скрипт задумывался для поиска, а при достаточно точном позиционировании и для замены совпадений в программах, в которых поиск по регуляркам не предусмотрен (напр. Fine Reader). С помощью эмуляций клавиш в программе выделяется текст от курсора до конца страницы (как вариант — абзаца). Копируем. Возвращаем курсор в исходное положение. Вычисляем в буфере обмена позицию и длину ПЕРВОГО совпадения — первого (ОДНОГО) совпадения от начала скопированного текста по всей совокупности регекспов). Эмуляцией {Right %FoundPos%} и +{Right %LastLine%} находим это совпадение в FR. Скрипт завершает свою работу. Следующее совпадение ищем от этого нового положения курсора. В общем речь идет о последовательном поиске совпадений по некоторому количеству регулярных выражений. По типу, как это делается в спеллчекере. Как-то же там это работает… Задача — найти какой из регекспов ПЕРВЫМ нашел это совпадение и выдать сообщение типа: "Найден начальный пробел". Ну и чтоб эти регулярки удобно и прозрачно было править.

13

Re: AHK: Поиск в буфере обмена по нескольким регекспам

stokber пишет:

найти какой из регекспов ПЕРВЫМ нашел это совпадение

Последние два примера это и демонстрируют.

Разработка AHK-скриптов:
e-mail dfiveg@mail.ru
Telegram jollycoder

14

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Да, уже попробовал. Это то, что надо. Всем спасибо!

15 (изменено: serzh82saratov, 2020-04-30 10:46:32)

Re: AHK: Поиск в буфере обмена по нескольким регекспам

teadrinker
Не знал про Mark. Можно ещё так обернуть, для удобства добавления, и выводить например сам шаблон если нужно.

str := "123abcd"

oPatterns := ["cd", "ab", "\d+"]

for k, v in oPatterns
	patterns .= "((*:" v ")" v ")|"
	
RegExMatch(str, "O)" RTrim(patterns, "|"), Match)

MsgBox, % "шаблон: " Match.Mark "`nпозиция: " Match.Pos "`nдлинна: " Match.Len "`nстрока: " Match.Value
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

16

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Спасибо! Для себя перелицевал вот таким образом:

str := "CDcd1233cdABCD123"
r1 := "(*:r1#строчные буквы)cd"
r2 := "(*:r2#Прописные буквы)AB"
r3 := "(*:r3#Числа)\d+"
oPatterns := [r1, r2, r3]
for k, v in oPatterns
	patterns .= "(" v ")|"
RegExMatch(str, "O)" RTrim(patterns, "|"), Match)
loop,parse, % Match.Mark, #
	c%A_Index%:=A_LoopField	
MsgBox, % "Шаблон: " c1 "`nКомментарий: " c2 "`nПозиция: " Match.Pos "`nДлина: " Match.Len "`nСтрока: " Match.Value

И два вопроса не дают покоя.
1. Хотел исхитриться, хоть и не очень на это и надеялся, отдельным регекспам присвоить ключи регистронезависимости i). Пришел к выводу, что это невозможно. Или всё-таки?
2. И в связи с п.1 и не только… Изначально решил пойти путем создания одного большого регулярного выражения с альтернативами. Вопрос: существует ли в AHK возможность сделать шаблоны соответствия более независимыми друг от друга, чтобы они могли иметь свои ключи и пополнялись бы простым добавлением и исключались бы комментированием?

17

Re: AHK: Поиск в буфере обмена по нескольким регекспам

stokber пишет:

перелицевал вот таким образом

Тогда уж так:


str := "CDcd1233cdABCD123"

oPatterns := {"r1`nстрочные буквы": "cd"
			, "r2`nПрописные буквы":"ab"
			, "r3`nЧисла": "\d+"}

for k, v in oPatterns
	patterns .= "((*:" k ")" v ")|"
	
RegExMatch(str, "O)" RTrim(patterns, "|"), Match)

MsgBox, % "шаблон: " Match.Mark "`nпозиция: " Match.Pos "`nдлинна: " Match.Len "`nстрока: " Match.Value
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

18 (изменено: serzh82saratov, 2020-05-02 17:40:27)

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Опции можно добавить в третьем параметре шаблона.


str := "CDcd1233cdABCD123"

oPatterns := [
	, ["r2_Прописные буквы", "AB"]
	, ["r1_строчные буквы", "cd", "i"]
	, ["r3_Числа", "\d+"]]

for k, v in oPatterns 
	patterns .= "((*:" v[1] ")" . (v[3] ? "(?" v[3] ")" : "") . v[2] ")|"  
	
RegExMatch(str, "O)" RTrim(patterns, "|"), Match)
c := StrSplit(Match.Mark, "_")

MsgBox, % "шаблон: " c[1] "`nКомментарий: " c[2]  "`nпозиция: " Match.Pos "`nдлинна: " Match.Len "`nстрока: " Match.Value
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

19

Re: AHK: Поиск в буфере обмена по нескольким регекспам

serzh82saratov пишет:
oPatterns := {"r1`nстрочные буквы": "cd"
			, "r2`nПрописные буквы":"ab"
			, "r3`nЧисла": "\d+"}

Это оно! Теперь можно и задокументировать ставшие ненужными, и добавить новые регекспы без необходимости править "patterns".
Только не смог разобраться как к этому коду приделать ключи.

20

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Так вы зачем из 17 код берёте, если про ключи (Опции) я только в 18 упоминаю.


oPatterns := [
	, ["r2_Прописные буквы", "AB"]
	, ["r1_строчные буквы", "cd", "i"]
	, ["r3_Числа", "\d+"]]
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

21

Re: AHK: Поиск в буфере обмена по нескольким регекспам

serzh82saratov
Ну, я как-то так и подумал. Но надежда теплилась… Для меня предпочтительнее все-же при отладке и наполнении регекспами не править "patterns"и не путаться там при большом количестве регулярок. Проще лишний раз «А-ЯЁ» вписать.  Огромное вам спасибо!

22

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Ничего не понял из вашего ответа, но к «А-ЯЁ» вписать по моему проще "i", чего вы и хотели добиться, а сейчас вдруг перехотели.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

23

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Я попробовал добавить в "Opatterns" из 18-го поста ещё регулярных выражений, скрипт заругался. Очевидно, нужно править ещё и "patterns". В случае кода из 17-го, скрипт сразу стал искать новые совпадения без каких либо правок в "patterns". Поэтому я и предпочел код из 17-го. Или я по своей дремучести что-то не понял?

24 (изменено: serzh82saratov, 2020-05-02 22:41:55)

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Скорее последнее.
Почему нельзя сразу сказать об этом, и привести скриншот ошибки?
Или код который не работает.

По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

25

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Почему-то решил, что это фича такая.
Проверил ещё раз. Неправильно указал характер ошибки.  При закомментировании одного из регекспов сработало не корректно. В сообщении были только номер шаблона и позиция. Комментарий и строка — пусто. Недостаточно тщательно проверил и наверное сделал неправильные выводы. Причина, кажется, в том, что в моем случае осталось всего два рабочих регекспа:

str := ".1233cdABCD123"
oPatterns := [

	, ["r1_Прописные буквы", "AB"]
;	, ["r2_строчные буквы", "cd", "i"]
;	, ["r3_Точки", "\."]
	, ["r4_Числа", "\d+"]]

for k, v in oPatterns 
	patterns .= "((*:" v[1] ")" . (v[3] ? "(?" v[3] ")" : "") . v[2] ")|"  
	patterns .= "((*:" k ")" v ")|"
	RegExMatch(str, "O)" RTrim(patterns, "|"), Match)
c := StrSplit(Match.Mark, "_")
MsgBox, % "шаблон: " c[1] "`nКомментарий: " c[2]  "`nпозиция: " Match.Pos "`nдлинна: " Match.Len "`nстрока: " Match.Value

Каюсь.

26

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Опять ничего не понял. Ощущение что есть проблемы, но я о них сам должен догадаться.
Это откуда?


	patterns .= "((*:" v[1] ")" . (v[3] ? "(?" v[3] ")" : "") . v[2] ")|"  
	patterns .= "((*:" k ")" v ")|"
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

27

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Так не работало, и решили от себя добавить?


str := ".1233cdABCD123"
oPatterns := [

	, ["r1_Прописные буквы", "AB"]
;	, ["r2_строчные буквы", "cd", "i"]
;	, ["r3_Точки", "\."]
	, ["r4_Числа", "\d+"]]
 
for k, v in oPatterns 
	patterns .= "((*:" v[1] ")" . (v[3] ? "(?" v[3] ")" : "") . v[2] ")|"  
	
RegExMatch(str, "O)" RTrim(patterns, "|"), Match)
c := StrSplit(Match.Mark, "_")

MsgBox, % "шаблон: " c[1] "`nКомментарий: " c[2]  "`nпозиция: " Match.Pos "`nдлинна: " Match.Len "`nстрока: " Match.Value
По вопросам возмездной помощи пишите на E-Mail: serzh82saratov@mail.ru Telegram: https://t.me/sergiol982
Win10x64 AhkSpy, Hotkey, ClockGui

28

Re: AHK: Поиск в буфере обмена по нескольким регекспам

Да уж. Смешались кони, люди… Тысяча извинений. И огромное спасибо за долготерпение и отзывчивость. Всего доброго!
Пора, наверное, спать.

29

Re: AHK: Поиск в буфере обмена по нескольким регекспам

serzh82saratov
Пока писал-отправлял последний пост пришло ваше сообщение. На мониторе в Notepade++ в двух областях экрана были окрыты оба скрипта. Таскал оттуда-сюда регекспы для теста и по-видимому натаскал лишнего.