Регулярные выражения
Регулярные выражения (англ.
RegularExpression) — это формальный язык поиска и осуществления манипуляций с подстроками в тексте, основанный на использовании мета символов
По сути это строка-образец (англ. pattern, по-русски её часто называют «шаблоном», «маской»), состоящая из символов и мета символов и задающая правило поиска
Вся суть применения регулярных выражений практически сводится к правильному построению шаблона для поиска.
А сам код поиска остаётся в принципе неизменен:
String.s = "строка в которой производится поиск"
Find.s ="шаблон поиска"
CreateRegularExpression(0,Find,#PB_RegularExpression_DotAll)
Dim Matched.s(10)
Matching.i = ExtractRegularExpression(0,String,Matched())
For i = 0 To (Matching - 1)
Debug Matched(i) ;результат
Next
FreeRegularExpression(0)
;
Например из строки текста нужно получить все конструкции заключенные в одинарные кавычки:
String.s = "Искомое слово начинаться например с 'динарные кавычки' Средний строка может 'быть' что угодно"
;(') ;Искомое слово начинаться например с '
;\S ;Не пробел
;(.*?) ;Средний строка может быть что угодно.
;(') ;Искомое слово должна заканчиваться например на '
Find.s ="(')\S(.*?)(')"
CreateRegularExpression(0,Find,#PB_RegularExpression_DotAll)
Dim Matched.s(10)
Matching.i = ExtractRegularExpression(0,String,Matched())
For i = 0 To (Matching - 1)
Debug Matched(i)
Next
FreeRegularExpression(0)
;
Интересен вариант, когда нужно исключит из найденных слов, шаблоны начала и конца поиска, в верхнем варианте это одинарные кавычки, или может быть любая другая конструкцию.
Можно воспользоваться функцией
RemoveString(), а можно применить другой шаблон для поиска:
String.s = "Искомое слово начинаться например с 'динарные кавычки' Средний строка может 'быть' что угодно"
;(?<=()') ;Искомое слово начинаться например с ' конструкция (?<=()') убирает '
;\S ;Не пробел
;(.*?) ;Средний строка может быть что угодно.
;(?=()') ;Искомое слово должна заканчиваться например на ' конструкция (?=()') убирает '
Find.s ="(?<=()')\S(.*?)(?=()')"
CreateRegularExpression(0,Find,#PB_RegularExpression_DotAll)
Dim Matched.s(10)
Matching.i = ExtractRegularExpression(0,String,Matched())
For i = 0 To (Matching - 1)
Debug Matched(i)
Next
FreeRegularExpression(0)
;
Пример нахождения IP адреса:
String.s = "IP:92.113.63.76 нужно выделить из текста все IP адреса http://127.0.0.1/ "
Find.s ="([0-9][0-9][0-9]|[0-9][0-9]|[0-9]).([0-9][0-9][0-9]|[0-9][0-9]|[0-9]).([0-9][0-9][0-9]|[0-9][0-9]|[0-9]).([0-9][0-9][0-9]|[0-9][0-9]|[0-9])"
CreateRegularExpression(0,Find,#PB_RegularExpression_DotAll)
Dim Matched.s(10)
Matching.i = ExtractRegularExpression(0,String,Matched())
For i = 0 To (Matching - 1)
Debug Matched(i)
Next
FreeRegularExpression(0)
;
Подробно о построении шаблонов поиска написано на страницах:
http://www.softring.ru/articles/perlregexp1.html
http://www.softring.ru/articles/perlregexp2.html
http://www.softring.ru/articles/perlregexp3.html
Синтаксис регулярных выражений
Таблица: Мета символы в регулярных выражениях
Символ | Описание |
\ | Для символов, которые обычно трактуются буквально, означает, что следующий символ является метасимволом. Например, /n/ соответствует букве n, а /\n/ соответствует символу перевода строки. Для метасимволов означает, что символ должен пониматься буквально. Например, /^/ означает начало строки, а /\^/ соответствует просто символу ^. /\\/ соответствует обратной косой черте \. |
^ | Соответствует началу строки (ср. модификатор m). |
$ | Соответствует концу строки (ср. модификатор m). |
. | Соответствует любому символу, кроме разрыва строки (ср. модификатор s). |
* | Соответствует повторению предыдущего символа нуль или более раз. |
+ | Соответствует повторению предыдущего символа один или более раз. |
? | Соответствует повторению предыдущего символа нуль или один раз. |
(pattern) | Соответствует строке pattern и запоминает найденное соответствие. |
x|y | Соответствует x или y. |
{n} | n — неотрицательное число. Соответствует ровно n вхождениям предыдущего символа. |
{n,} | n — неотрицательное число. Соответствует n или более вхождениям предыдущего символа. /x{1,}/ эквивалентно /x+/. /x{0,}/ эквивалентно /x*/. |
{n,m} | n и m — неотрицательные числа. Соответствует не менее чем n и не более чем m вхождениям предыдущего символа. /x{0,1}/ эквивалентно /x?/. |
[xyz] | Соответствует любому символу из заключенных в квадратные скобки. |
[^xyz] | Соответствует любому символу, кроме заключенных в квадратные скобки. |
[a-z] | Соответствует любому символу в указанном диапазоне. |
[^a-z] | Соответствует любому символу, кроме лежащих в указанном диапазоне. |
\a | Соответствует символу звонок (BEL). |
\A | Соответствует только началу строки, даже с модификатором m. |
\b | Соответствует границе слова, т. е. позиции между \w и \W в любом порядке. |
\B | Соответствует любой позиции, кроме границы слова. |
\сX | Соответствует символу Ctrl+X. Например, /\cI/ эквивалентно /\t/. |
\C | Соответствует одному байту, даже при директиве use utf8. |
\d | Соответствует цифре. Эквивалентно [0-9]. |
\D | Соответствует нецифровому символу. Эквивалентно [^0-9]. |
\e | Соответствует символу escape (ESC). |
\E | Конец преобразований \L, \Q, \U. |
\f | Соответствует символу перевода формата (FF). |
\G | Соответствует позиции в строке, равной pos(). |
\l | Преобразует следующий символ в нижний регистр. |
\L | Преобразует символы в нижний регистр до \E. |
\n | Соответствует разрыву строк. |
\pproperty | Соответствует символам Unicode, обладающим свойством property. Если property задается несколькими символами, используйте синтаксис \p{property}. |
\Pproperty | Соответствует символам Unicode, не обладающим свойством property. Если property задается несколькими символами, используйте синтаксис \P{property}. |
\Q | Добавляет символ "\" перед метасимволами до \E. |
\r | Соответствует символу возврата каретки (CR). |
\s | Соответствует символу пробела. Эквивалентно /[ \f\n\r\t]/. |
\S | Соответствует любому непробельному символу. Эквивалентно /[^ \f\n\r\t]/. |
\t | Соответствует символу табуляции (HT). |
\u | Преобразует следующий символ в верхний регистр. |
\U | Преобразует символы в верхний регистр до \E. |
\w | Соответствует латинской букве, цифре или подчеркиванию. Эквивалентно /[A-Za-z0-9_] /. |
\W | Соответствует любому символу, кроме латинской буквы, цифры или подчеркивания. Эквивалентно /[^A-Za-z0-9_] /. |
\X | Соответствует последовательности символов Unicode из основного символа и набора диакритических значков. Эквивалентно выражению /C<(?:\PM\pM*)>/. |
\z | Соответствует только концу строки, даже с модификатором m. |
\Z | Соответствует только концу строки или разрыву строк в конце строки, даже с модификатором m. |
\n | n — положительное число. Соответствует n-ной запомненной подстроке. Если левых скобок до этого символа меньше, чем n, и n > 9, то эквивалентно \0n. |
\0n | n — восьмеричное число, не большее 377. Соответствует символу с восьмеричным кодом n. Например, /\011/ эквивалентно /\t/. |
\xn | n — шестнадцатеричное число, состоящее из двух цифр. Соответствует символу с шестнадцатеричным кодом n. Например, /\x31/ эквивалентно /1/. |
\x{n} | n — шестнадцатеричное число, состоящее из четырех цифр. Соответствует символу Unicode с шестнадцатеричным кодом n. Например, /\x{2663}/ эквивалентно /♣/. |
| |
Расширенные образцы
Дополнительные конструкций, которые могут употребляться в регулярных выражениях для расширения их возможностей. Все эти конструкции заключаются в круглые скобки и начинаются с символа
?, что отличает их от запоминания подстрок.
(?#text)
Комментарий. Вся конструкция игнорируется.
(?modifiers-modifiers)
Включает или выключает заданные модификаторы. Модификаторы, стоящие до символа -, включаются, стоящие после него — выключаются.
Пример:
if (/aaa/) { … } # сопоставление с учетом регистра
if (/(?i)aaa/) { … } # сопоставление без учета регистра
(?:pattern)
(?modifiers-modifiers:pattern)
Позволяет группировать подвыражения регулярного выражения без запоминания найденного соответствия. Вторая форма дополнительно включает или выключает заданные модификаторы. Например, выражение /ко(?:т|шка)/ — это краткая запись выражения /кот|кошка/.
(?=pattern)
Соответствие с заглядыванием вперед без запоминания найденного соответствия. Например, выражение /Windows (?=95|98|NT|2000)/ соответствует "Windows" в строке "Windows 98", но не соответствует в строке "Windows 3.1". После сопоставления поиск продолжается с позиции, следующей за найденным соответствием, без учета заглядывания вперед.
(?!pattern)
Несоответствие с заглядыванием вперед без запоминания найденного соответствия. Например, выражение /Windows (?!95|98|NT|2000)/ соответствует "Windows" в строке "Windows 3.1", но не соответствует в строке "Windows 98". После сопоставления поиск продолжается с позиции, следующей за найденным соответствием, без учета заглядывания вперед.
(?<=pattern)
Соответствие с заглядыванием назад без запоминания найденного соответствия. Например, выражение /(?<=\t)\w+/ соответствует слову, следующему за символом табуляции, и символ табуляции не включается в $&. Фрагмент, соответствующий заглядыванию назад, должен иметь фиксированную ширину.
(?<!pattern)
Несоответствие с заглядыванием назад без запоминания найденного соответствия. Например, выражение /(?<!\t)\w+/ соответствует слову, перед которым нет символа табуляции. Фрагмент, соответствующий заглядыванию назад, должен иметь фиксированную ширину.
К примеру, код сканирующий ваши жесткие диски (в коде нужно правильно указать название дисков), находит файлы с расширением
PureBasic pb и
pbi, производит в них поиск по шаблону:
"(?<![\.\w])[a-zA-Z_]\w*(?=(?:\.\w+\s*|\s*)\()"
и составляет список
TOP-20 самых популярных функций.
Поиск происходит долго, нужно терпение...
Enumeration
#RegularExpression
EndEnumeration
CreateRegularExpression(#RegularExpression, "(?<![\.\w])[a-zA-Z_]\w*(?=(?:\.\w+\s*|\s*)\()")
Structure Befehl
Name$
Count.i
EndStructure
Global NewMap Befehl.i()
Global NewList Befehl2.Befehl()
Procedure FindAlFiles(DirectoryName$)
Debug ">> "+DirectoryName$
Protected File, Count, i
Protected Dim Result$(0)
Protected Directory = ExamineDirectory(#PB_Any, DirectoryName$, "*")
If Directory
While NextDirectoryEntry(Directory)
Select DirectoryEntryType(Directory)
Case #PB_DirectoryEntry_Directory
If DirectoryEntryName(Directory) <> "." And DirectoryEntryName(Directory) <> ".."
FindAlFiles(DirectoryName$+"\"+DirectoryEntryName(Directory))
EndIf
Case #PB_DirectoryEntry_File
If Left(GetExtensionPart(DirectoryEntryName(Directory)),2)="pb"
File = ReadFile(#PB_Any, DirectoryName$+"\"+DirectoryEntryName(Directory))
If File
Repeat
String$ = ReadString(File)
Count = ExtractRegularExpression(#RegularExpression, String$, Result$())
For i = 0 To Count-1
Befehl(Result$(i)) + 1
Next
Until Eof(File)
CloseFile(File)
EndIf
EndIf
EndSelect
Wend
EndIf
EndProcedure
;FindAlFiles("D:\")
FindAlFiles("C:\")
FindAlFiles("F:\")
ForEach Befehl()
AddElement(Befehl2())
Befehl2()\Name$ = MapKey(Befehl())
Befehl2()\Count = Befehl()
Next
SortStructuredList(Befehl2(), #PB_Sort_Descending, OffsetOf(Befehl\Count), #PB_Sort_Integer)
Top10 = 1
ForEach Befehl2()
Debug Str(Top10)+". "+Befehl2()\Name$+" [ "+Str(Befehl2()\Count)+" ]"
Top10 + 1
If Top10 = 21 : Break : EndIf
Next
;
Моя двадцатка:
1. sgx [ 8846 ]
2. RGB [ 8567 ]
3. Chr [ 7381 ]
4. Str [ 6967 ]
5. sgx_keyLay [ 5232 ]
6. MessageRequester [ 4265 ]
7. WindowID [ 3870 ]
8. ImageID [ 3682 ]
9. AddGadgetItem [ 3675 ]
10. SetGadgetText [ 3101 ]
11. OpenWindow [ 3069 ]
12. SetGadgetState [ 3032 ]
13. Box [ 2941 ]
14. Random [ 2896 ]
15. ButtonGadget [ 2651 ]
16. v4 [ 2569 ]
17. StartDrawing [ 2538 ]
18. StopDrawing [ 2537 ]
19. Len [ 2487 ]
20. CallFunction [ 2385 ]