Описание функции


StringRegExp

Ищет в строке совпадения с образцом, заданным в виде регулярного выражения.

StringRegExp('test','pattern'[,flag=0[,offset=1]])

Параметры

test Строка для поиска.
pattern Образец для поиска (шаблон).
flag [необязательный] Флаг, определяющий поведение функции. См. ниже. По умолчанию равен 0.
offset [необязательный] Позиция строки, начиная с которой будут искаться совпадения (нумерация начинается с 1). По умолчанию равен 1.

flag Поведение
0 Возвращает 1 (совпадение найдено) или 0 (не найдено).
1 Поиск до первого совпадения; возвращает массив групп, а при отсутствии групп одноэлементный массив с полным совпадением шаблона (см. примечания).
2 Поиск до первого совпадения; возвращает массив содержащий в первом элементе полное совпадение с шаблоном, последующие элементы - совпадение указанных групп (стиль Perl / PHP).
3 Возвращает массив всех полных совпадений с шаблоном.

Примечания

Параметр flag может принимать значения (от 0 до 3). При flag = 0, функция возвращает 1 (найдено) или 0 (не найдено). Если флаг равен 1 или 2, то функция находит первое совпадение и возвращает его в виде массива. Если флаг равен 3 или 4, то функция находит все возможные совпадения и возвращает их в массиве. Если флаг равен 2 или 4, то возвращаемые массивы содержат полное совпадение с шаблоном и совпадения групп, а не только полное совпадение, как при использовании флага 1 или 3.

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

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

Символы повтора (*, +, ?, {...} ) будут соответствовать строке наибольшей длины, если сразу же за ними не идёт символ вопросительный знак '?' (в этом случае часть шаблона будет соответствовать строке наименьшей длины).

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

Осторожно: неправильно написанное регулярное выражение может стать причиной зацикливания и даже вызвать сбой работы скрипта.


Метасимволы вне квадратных скобок

( ) начало и конец группы, например (text). Означают последовательность. Используются для применения квантификаторов не к одному символу, а к нескольким, а также для дальнейшего использования найденной последовательности.
[ ] начало и конец описания символьного класса, например [a-z]. Символьный класс возвращает один символ из множества. Изменить это могут повторители.
{ } начало и конец повторителей, например {3,8}
\ экранирующий символ, принять метасимвол как обычный символ, например (\\, \., \[, \], \{, \}, \*).
^ начало строки (или начало текста в многострочных текстах), например ^text text$
$ конец строки (или конец текста в многострочных текстах), например ^text text$
. любой символ, кроме переноса строки @LF (по умолчанию). С флагом (?s) - любой символ
| символ "или", обычно внутри группы, например (10|20)
? предыдущий символ либо имеется, либо не имеется, аналогично и для групп. После символа повтора - жадность паттерна - (.*?)
* повтор предыдущего символа или группы 0 и более раз
+ повтор предыдущего символа или группы 1 и более раз

Метасимволы внутри квадратных скобок

Часть шаблона, заключенная в квадратные скобки, называется символьным классом. Внутри скобок метасимволы теряют свое специальное значение, кроме метасимволов, принадлежащих этому классу. Экранировать требуется только 4 символа \ - ] [. Если символ "-" находится в конце перечисления, то не требует экранирования. В шаблоне могут использоваться метасимволы диапазонов, но не используются метасимволы границ, например \A, \B, \Z, \z, а метасимвол \b означает символ возврата 'backspace'. Учтите, что диапазоны, например [а-я] используют UTF-8 последовательность, а не ASCII.

\ экранирующий символ
^ символ исключения, но в случае, когда стоит первым, например [^3] все кроме три
- символ охвата, например [a-z], то есть любой из символов от a до z
[ ] начало и конец описания символьного класса, например [a-z]

Метасимволы подстановки

\1 - \9 ссылка на найденную группу в самом шаблоне и в шаблоне замены
$1 - $9 ссылка на найденную группу в шаблоне замены (9 не ограничение)
$0 или \0 весь шаблон поиска
\a Chr(7) - символ с десятичным ASCII-кодом 7 (звонок). При выводе воспроизводит звуковой сигнал. BEL (hex 07)
\cn управляющий символ, который генерируется при нажатии комбинации клавиш Ctrl+n, где n- символ, например \cD соответствует Ctrl+D. \cA = \001, \cZ = \032, \cM = \r = \015
\e Chr(27) - символ escape (hex 1B)
\f Chr(12) перенос страницы (hex 0C)
\h [ \t] любой горизонтальный пробел, табуляция - Chr(9), Chr(32), Chr(160)
\H [^\h] - любой символ, который не пробел или табуляция
\K reset start of match.
\n @LF, Chr(10) - символ переноса на новую строку (hex 0A)
\N [^\n] Любой символ, который не символ переноса на новую строку (не @LF). Не работает в 3.3.6.1
\Q ... \E любые метасимволы между \Q и \E воспринимаются как текст. Не исключайте ошибки: \QD:\Edit\1.txt\E
\r @CR, Chr(13) - символ возврат каретки (hex 0D)
\R [\n\f\r\v] Chr(10), Chr(11), Chr(12), Chr(13) любой из символов переноса строки
\t @TAB, Chr(9) символ табуляции - tab (hex 09)
\v [\r\n\f] Chr(10), Chr(11), Chr(12), Chr(13) вертикальная табуляция (@CR и @LF и перенос страницы)
\V [^\v] - любой символ, который не Chr(10), Chr(11), Chr(12), Chr(13) вертикальная табуляция (перенос строки)
\x** где * - любая шестнадцатеричная цифра, например \x41 соответствует латинской букве 'A', \x50\x65\x72\x6C - слово Perl
\x{**..} где * - любая шестнадцатеричным цифра, например \x{50}\x{65}\x{72}\x{6C} - слово Perl. Попробуйте от \x{01} до \x{7F}, что в десятеричной системе означает символы от 1 до 127. Или в UTF кодировке \x{044F} равный символу "я"
\*** где * - любая восьмеричная цифра. Например, последовательность \120\145\162\154 представляет слово Perl (\120 - восьмеричный код буквы Р, \145 - буквы е, \162 - буквы r, \154 - буквы l). Пробел - \040. Попробуйте от \001 до \177, что в десятеричной системе означает символы от 1 до 127
\G обозначает точку, в которой закончился предыдущий поиск (first matching position in subject)

Метасимволы для задания диапазонов символов

\d [0-9] - любая десятичная цифра
\D [^0-9] любая не цифра
\s [\f\n\r\t\v ] - пустой символ: Chr(9), Chr(10), Chr(12), Chr(13), Chr(32) (перенос страницы, табуляция, возврат каретки, перевод строки и пробел).
\S [^\f\n\r\t\v ] - любой непробельный символ
\w [0-9a-zA-Z_] - любой алфавитно-числовой символ или подчеркивание (только символы латинского алфавита)
\W [^0-9a-zA-Z_] - любой символ неслова

Границы символов

\A Начало текста, не зависит от флага "(?m)" и поэтому может встретится только 1 раз
\z Исключительно конец текста, не зависит от флага "(?m)" и поэтому может встретится только 1 раз
\Z Конец текста, т. е. граница между любым символом и концом текста или до символа \n, если он в конце строки, не зависит от флага "(?m)" и поэтому может встретится только 1 раз.
\b начало или конец слова, т. е. граница между символами, один из которых удовлетворяет \W, а другой - удовлетворяет \w (только границы слов латинского алфавита)
\B Середина слова, т. е. граница между символами, оба которых удовлетворяют \W или оба которых удовлетворяют \w

Флаги модификаторы

Ставятся в начало регулярного выражения или группы. Состояние модификаторов выключено по умолчанию, соответственно для использования требуется включить.
Пример использования : (?i)(Text) или ((?-i)Text), допустимо комбинировать (?is)(Text) или ((?imsx)Text)

(?i) не учитывать регистр символов. Это работает только для символов латинского алфавита.
(?-i) отменяет ранее включенный (?i)
(?m) в многострочном тексте символы ^ и $ означают начало и конец строки соответственно, иначе начало и конец текста
(?-m) отменяет ранее включенный (?m)
(?s) символ "точка" (.) дополнительно включает в себя перенос строки @LF (режим "одна строка")
(?-s) отменяет ранее включенный (?s)
(?x) игнорирует пробелы и табуляции в регулярном выражении, кроме тех что в квадратных скобках. Пробелы позволяют сделать регулярное выражение легко читаемым. Позволяет в конце рег. выр. добавить комментарий после символа # и до конца строки
(?-x) отменяет ранее включенный (?x)
(?J) allow duplicate names (разрешает дубликаты/двойные названия).
(?U) инвертировать жадность квантификаторов
(?-U) отменяет ранее включенный (?U)

Флаги групп

Допустимо комбинировать, например (?im-sx:Text), флаги sx выключены

(?i:...) группа не учитывает регистр символов, например (?i:Text)
(?-i:...) группа учитывает регистр символов, например (?-i:Text)
(?:...) исключает группу из найденных, например (?:Text)
(?>...) группа не входящая в поиск, но имеет свойство сверхжадного квантификатора, например (?>Text)(Text)
(?=...) группа не входящая в поиск, но проверяющая совпадение образца справа, например (Text)(?=Text)
(?!...) группа не входящая в поиск, но проверяющая не совпадение образца справа, например (Text)(?!Text)
(?<=...) группа не входящая в поиск, но проверяющая совпадение образца слева, например (?<=Text)(Text)
(?<!...) группа не входящая в поиск, но проверяющая не совпадение образца слева, например (?<!Text)(Text)
(?<name>...) именованная ссылка. Вызов именованной ссылки \k<name> это тоже что вызов \1 или $1
(?#...) группа содержащая комментарий, например (?# это комментарий ). Полностью игнорируется интерпретатором

Повтор предыдущего элемента, применяется к символам и группам (квантификаторы)

{n} повторить предыдущий символ n раз
{n,} повторить предыдущий символ n и более раз ( {n,}? - предпочтительно наименьший захват)
{n, m} повторить предыдущий символ от n до m раз ( {n,m}? - предпочтительно наименьший захват)
* повторить предыдущий символ 0 и более раз. То же что и {0,}. Жадный захват, наибольший, который позволит совпасть оставшейся части шаблона.
+ повторить предыдущий символ 1 и более раз. То же что и {1,}. Жадный захват, наибольший, который позволит совпасть оставшейся части шаблона.
? предыдущий символ либо имеется, либо не имеется. То же что и {0, 1}. Второе значение символа ? после символа повтора .*? - жадность, см. ниже
*? повторить предыдущий символ 0 и более раз. Ограничится наименьшим захватом (не жадный), который позволит совпасть оставшейся части шаблона.
+? повторить предыдущий символ 1 и более раз. Ограничится наименьшим захватом (не жадный), который позволит совпасть оставшейся части шаблона.
?? предпочтительно наименьший захват, например ([a-z]??)g для 'gg' возвращает две пустые строки

Ревнивая или сверхжадная квантификация

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

*+ повторить предыдущий символ 0 и более раз.
++ повторить предыдущий символ 1 и более раз.
{n,}+ повторить предыдущий символ n и более раз.

Символьные классы POSIX

Пример [[:upper:]]{2} - поиск повтора заглавных букв. Инвертировать диапазон так: [[:^digit:]]

[:alnum:] буквы и цифры [0-9A-Za-z] (как \w, но без "_")
[:alpha:] буквы [A-Za-z] (без "_")
[:ascii:] символы от Chr(0) до Chr(127)
[:blank:] пробел и символ табуляции Chr(9) и Chr(32), тоже что [\t ]
[:cntrl:] управляющие символы от Chr(0) до Chr(31) и Chr(127)
[:digit:] десятичные цифры, тоже что \d, [0-9]
[:graph:] тоже что символы, отображаемые при печати [:print:], но кроме пробела (от Chr(33) до Chr(126) )
[:lower:] прописные буквы [a-z]
[:print:] символы, отображаемые при печати, включая пробел (от Chr(32) до Chr(126) )
[:punct:] символы, отображаемые при печати, кроме букв и цифр Chr=(33-47, 58-64, 91-96, 123-126), те, что не входят ни в [:alnum:], ни в [:cntrl:]
[:space:] пробельные символы (как \s, но включая символ VT: Chr(11) ) от Chr(9) до Chr(13) и Chr(32). Тоже что [\f\n\r\t\v ]
[:upper:] заглавные буквы [A-Z]
[:word:] символы слов, тоже что \w
[:xdigit:] шестнадцатеричные цифры [0-9A-Fa-f]

Условные подмаски

(?(если)то) например (?(?=[a-z])\d), (?(условие)шаблон_при_успехе)
(?(если)то|иначе) например (?(?<=\d)a|b) или (?:(?>(?=[^a-z]*[a-z])())?(?:(?=\1)aa|(?!\1)1)), (?(условие)шаблон_при_успехе|шаблон_при_не_успехе)
(?=[\w]+)| (?R) рекурсивный вызов

Эти флаги не действуют в AutoIt3

\p любой символ пунктуации
\l означает, что следующий символ регулярного выражения преобразуется в нижний регистр.
\u означает, что следующий символ регулярного выражения преобразуется в верхний регистр.
\L...\Е означает, что все символы в регулярном выражении между \L и \Е преобразуются в нижний регистр.
\U...\Е означает, что все символы в регулярном выражении между \U и \Е преобразуются в верхний регистр.
\x любой шестнадцатеричный символ
\< начало слова, т. е. граница между символом, удовлетворяющим \W и символом, удовлетворяющим \w
\> конец слова, т. е. граница между символом, удовлетворяющим \w и символом, удовлетворяющим \W
{,n} повторить предыдущий символ от 0 до n раз

Примеры конструкций

.* повтор любого символа, а значит весь текст
[ ... ] одиночный символ множества, например [aeiou] - любой из строчных гласных
[^ ... ] ни один из символов множества, например [^aeiou] - ни один из строчных гласных
[0-9A-Fa-f]{6} Шестнадцатеричное число, например FF0000.
[А-яёЁ] диапазон для русских букв. Или так [А-Яа-яёЁ]

Примеры
Найти (\r\n|\r|\n){2,} заменить на \1 - удаляет пустые строки
Найти (?<![^\s\A])([А-яёЁ]+)[\h]+\1 заменить на \1 - удаляет повторы слов
Найти [A-ZА-ЯЁ]{2,}?[a-zа-яё]+ - выявляет файлы, в которых есть ошибки вида "НАйти"- не преднамеренный повтор заглавной буквы
Найти (.{35,}?)\h заменить на '$1'&@CRLF - выполняет перенос строки на границе первого попавшегося пробела после каждых 35 символов.
Найти (?si)(?:.*?)?(https?://[\w.:]+/?(?:[\w/?&=.~;\-+!*_#%])*) - найти ссылки
Найти [A-Za-z0-9._-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}) - найти почтовые ящики

Функцию можно подключить через команду exect
Для передачи пустой строки можно воспользоваться ключевым словом Null
Для передачи значения по умолчанию можно воспользоваться ключевым словом Default

См. также

StringRegExpReplace, StringInStr

Примеры:
 Как создать кнопку?


exect=$var_s=ClipGet()||$var_n=StringRegExp('$var_s','(\d{1,4}x\d{1,4})') <IF> $var_n = 0 <THEN> exect=$var_s='100x100' <ENDIF> exect=_ViewValues('$var_s') ;; если содержимое буфера обмена не является строкой вида 0x0 или 00x00 или 000x000 или 0000x0000 (где вместо нуля может быть любая цифра), то переменная $var_s=100x100

exect=$var_s0=ClipGet()||$var_s1=StringRegExp('$var_s0','(\d{1,4}x\d{1,4})')=0?'100x100':'$var_s0'||_ViewValues('$var_s1') ;; если содержимое буфера обмена не является строкой вида 0x0 или 00x00 или 000x000 или 0000x0000 (где вместо нуля может быть любая цифра), то переменная $var_s=100x100

exect=$var_s1=StringRegExp(ClipGet(),'(\d{1,4}x\d{1,4})')=0?'100x100':ClipGet()||_ViewValues('$var_s1') ;; если содержимое буфера обмена не является строкой вида 0x0 или 00x00 или 000x000 или 0000x0000 (где вместо нуля может быть любая цифра), то переменная $var_s=100x100

exect=$var_s=##[input=BOX73]||$var_ar=StringRegExp(FileRead(@CRLF&'C:\dictionary.txt'&@CRLF),'[\r\n](['&'$var_s'&']+)[\r\n]',3)||_ViewValues($var_ar)||$var_s=_ArrayToString($var_ar,@CRLF) bufsr=##$var_s ;; отправить в буфер обмена все слова, составленные из введённых в диалоге букв, которые входят в состав словаря dictionary.txt (В список входят слова, с перестановкой всех букв заданного набора с повторами букв без точной длины)
exect=$var_s=##[input=BOX73]||$var_ar=StringRegExp(@CRLF&FileRead('C:\dictionary.txt')&@CRLF,'[\r\n](['&'$var_s'&']{3,6})[\r\n]',3)||_ViewValues($var_ar)||$var_s=_ArrayToString($var_ar,@CRLF) bufsr=##$var_s ;; отправить в буфер обмена все слова, составленные из введённых в диалоге букв, которые входят в состав словаря dictionary.txt (В список входят слова, с перестановкой всех букв заданного набора с повторами букв и длина 5 символов)
exect=$var_s=##[input=BOX73]||$var_ar=StringRegExp(@CRLF&FileRead('C:\dictionary.txt')&@CRLF,'[\r\n](['&'$var_s'&']{5})[\r\n]',3)||_ViewValues($var_ar)||$var_s=_ArrayToString($var_ar,@CRLF) bufsr=##$var_s ;; отправить в буфер обмена все слова, составленные из введённых в диалоге букв, которые входят в состав словаря dictionary.txt (В список входят слова, с перестановкой всех букв заданного набора с повторами букв и длина от 3 до 6 символов)
exect=$var_s=##[input=BOX73]||$var_ar=StringRegExp(@CRLF&FileRead('C:\dictionary.txt')&@CRLF,'[\r\n](['&'$var_s'&']{[input=BOX74],[input=BOX75]})[\r\n]',3)||_ViewValues($var_ar)||$var_s=_ArrayToString($var_ar,@CRLF) bufsr=##$var_s ;; отправить в буфер обмена все слова, составленные из введённых в диалоге букв, которые входят в состав словаря dictionary.txt (В список входят слова, с перестановкой всех букв заданного набора с повторами букв и длина задаётся в диалоге)
exect=$var_ac=StringRegExp(ClipGet()&@CR&@CR,'(?m)^([^\r\n]*)',3)||$var_ab=StringSplit('TOTALCMD#BAR#DATA|%%COMMANDER_PATH%%\TCIMG.exe|#|Wcmicons.dll,0|','|',2)||$var_ab[2]=$var_ac[0]||$var_ab[4]=$var_ac[1]||_ArrayToClip($var_ab,@CRLF) ;; из 2-х строк в буфере обмена (команда и описание) создать кнопку TCIMG для Total Commander и записать в буфер обмена

exect=_ViewValues(StringRegExp(ClipGet(),'(?m)^([^\r\n]*)',3)) ;; разбить содержимое буфера обмена в массив построчно и просмотр массива

exect=_ViewValues(StringRegExp(FileRead('%P%N'),'(?m)^([^\r\n]*)',3),'%P%N') ;; разбить содержимое файла под курсором в массив построчно и просмотр массива

sends=-1 exect=$var_a='GLOBALSENDS<1>' GLOBALEXECT<a> exect=$var_name=StringRegExp('GLOBALEXECT<1>','^[~~-_]?$',0)?'>':'test'||_ViewValues('$var_name') ;; пример проверки буфера обмена: если в буфере пробел, "-", "_" или пустой, то в $var_name записывается знак > , иначе test

exect=$var_a=StringRegExp(FileRead('%P%N'),'(?ms)@font-face(?:[\s]+)?\{[^\{]+\}',3)||_ViewValues($var_a) ;; разбить в массив файл css под курсором все фрагменты @font-face

exect=$var_a=StringRegExp(FileRead('%P%N'),'(?ms)@font-face(?:[\s]+)?\{[^\{]+\}',3)||_ViewValues($var_a)||$var_a=_ArrayUnique($var_a)||_ViewValues($var_a) ;; разбить в массив файл css под курсором все фрагменты @font-face и удалить дубликаты фрагментов

sends=\<link\h+rel\=[\''|\']?[^>]+\>??1 exect=$var_a=_ArrayUnique(StringRegExp(FileRead('%P%N'),$GLOBALSENDS[1],3))||_ViewValues($var_a) ;; получить заданные отрезки файла под курсором и отобразить их в таблице

exect=$var_s=ClipGet()||$var_i=StringRegExp(ClipGet(),'([^A-Za-z\d])',0)?MsgBox(48+4096,'Результат','Число~~в~~буфере~~не~~является~~хэшем.')&_Exit():1||$var_i=StringLen('$var_s')||$var_n=$var_i=8?3:($var_i=32?1:($var_i=64?6:($var_i=128?8:MsgBox(48+4096,'Результат','Число~~в~~буфере~~не подходит~~под~~условие~~проверки.')&_Exit())))||$var_path=$var_n&'%P%N' <IF> <info=f$var_path|1//> = $var_s <THEN> exect=MsgBox(64+4096,'Результат','Контрольные~~суммы~~совпадают.') <ELSE> exect=MsgBox(48+4096,'Результат','Контрольные~~суммы~~не~~совпадают.') <ENDIF> ;; сравнить контрольные суммы файла под курсором и буфера обмена, в зависимости от длины строки буфера: если 8, то сравнение происходит по CRC32, если 32 - MD5, если 64 - SHA256, если 128 - SHA512, в сплывающем окне с ручным закрытием, сообщить результат

exect=$var_s=StringRegExp(ClipGet(),'(?i)^[a-z]',0)?'1,2':'2,1' sends=-1!!-1||#L$var_s GLOBALSENDS<a> ;; если в буфере обмена первая буква кириллицы, то поменять 1-ю и 2-ю строки

exect=$var_a=StringRegExp(FileRead('%P%N'),'(?m)((?:[^\r\n]+(?:\r\n|$)+){5})',3)||_ViewValues($var_a) ;; разбить текстовый файл под курсором по 5 строк

slist=%WL exect=$var_a=StringRegExp(FileRead('GLOBALSLIST<t>'),'(?m)((?:[^\r\n]+(?:\r\n|$)+){5})',3) GLOBALEXECT<a> ;; разбить пути выделенных объектов на группы по 5

slist=%WL exect=$var_a=StringRegExp(FileRead('GLOBALSLIST<t>'),'(?m)((?:[^\r\n]+(?:\r\n|$)+){1,5})',3) GLOBALEXECT<a> ;; разбить пути выделенных объектов на группы по 5 + остаток (если выделено не кратно 5)

arr2d=%WL||46|0|StringRegExp('::','(exe|ini|txt)$') GLOBALARR2D<a> ;; из выделенных файлов получить заданные типы

arr2d=%WL||45|0|StringRegExp('::','(exe|ini|txt)$') GLOBALARR2D<a> ;; из выделенных файлов получить типы, кроме заданных

<PRESW=13> keybd=0~~^c exect=$var_s=StringRegExp(StringLeft(ClipGet(),1),'[а-яё]')?_CmdCm('bufsr=@@QWERTYinENG'):_CmdCm('bufsr=@@QWERTYinRUS') keybd=0~~+{INSERT} <PRESW=1B> :EXIT: <PRESWEND> ;; при нажатии на клавиши "Pause" проверяет буфер обмена: если первая буква русская, то переводит всё содержимое буфера обмена в клавиатурные английские буквы, если нет, то наоборот, затем вставляет текст в активный окно программы

exect=$var_time=StringRegExp(BinaryToString(InetRead('http://currenttimestamp.com')),'current_time\h*=\h*(\d{10});',1)[0]||_ViewValues('$var_time') ;; получить текущую дату unix timestame сегодняшнего дня


© Аверин Андрей для Total Commander Image  Averin-And@yandex.ru