Регулярные выражения — ликбез по регэкспам
Регулярные выражения — ликбез по регэкспам
Очень хотелось бы больше примеров по регэкспам в документации, т.к. впервые столкнувшись с серьёзной задачей, разобраться очень трудно. Сколько ни бился, так и не получилось такое вот: имеется много html\xml файлов, в них теги прописаны большими, маленькими буквами и смешаным регистром. У тегов естессно, есть параметры, причём в виде: параметр=значение, параметр="значение", параметр='значение'. Требуется привести теги и их параметры, не имеющие смешаного регистра, к \l, при этом ни в коем случае не менять регистр значений. Более того, все значения нужно взять в кавычки.
Т.е. <A HREF=http://www.some.com/REG.HTML>...</A> нужно перевести в <a href="http://www.some.com/REG.HTML">...</a>
<SomeTag SomeParam=SomeValue /> перевести <SomeTag SomeParam="SomeValue" />,
а, допустим <meta http-equiv="Content-Type" content=text/html; charset=windows-1251> в <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251">
Задача номер следующая: теги, не имеющие закрывающую пару, и не закрывающиеся сами - закрыть. Т.е. те же <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251"> перевести в <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251" />
<img src="..."> в <img src="..." />
Я так понимаю, что задача выполнимая. Но как это сделать? По существующей документации разобраться очень трудно.
<img src="..."> - это если (<.*?\s)(.*?(?<![\/|\/\s])>) и как-то обозначить, что дальше по тексту не встречается $1.*?(?<=[\/|\/\s])> - как-то так...
То тогда менять на $1...[внутренности тега]... /> Во всяком случае такая строка поиска находит теги, не закрывающие сами себя... И в то же время такие вот вещи "<b> some </b>some<b>" (оказывается выделенным всё, что в кавычках). Но как дальше? И как избежать вот этих ошибок. Нужно как-то обозначить, что внутри $1 не должно быть ">" и вообще та закрывающая скобка, которая явно нарисована, должна быть первой закрывающей.
Да, ещё, нужно учесть, что закрывающий тег может быть и не в той же самой строке. А в сложных случаях - вложенность тегов...
И ещё, можно ли как-то указать, что группа должна быть больше, меньше, равно, не больше, не меньше, чем столько-то символов? Не считая, конечно, явного составления из "ровно один любой символ". Могу я для строки AZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX указав A.*X, указать ещё и длину не больше 15 символов? Хотя здесь ещё просто, а вот для предыдущих упражнений с тегами задавать длину не более 75 символов со всеми параметрами?
Как можно задать строку-исключение? "XXX" не должна входить в "A.*?Z".
Думаю, если подробный разбор этого дела сделать (с пояснениями), то практически с любой степенью сложности регэкспов можно будет справиться. Или есть и более сложные примеры?
(<(?!\/).+?\s(?<!>))(.*?(?<![\/|\/\s])>) находит "<b> some </b>", но не "<b> some </b>some<b>" (без кавычек).
А ещё "<pre><font size=4>".
(<(?!\/).+?[\s>](?<!>))(.*?(?<![\/|\/\s])>) и того хуже.
Т.е. <A HREF=http://www.some.com/REG.HTML>...</A> нужно перевести в <a href="http://www.some.com/REG.HTML">...</a>
<SomeTag SomeParam=SomeValue /> перевести <SomeTag SomeParam="SomeValue" />,
а, допустим <meta http-equiv="Content-Type" content=text/html; charset=windows-1251> в <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251">
Задача номер следующая: теги, не имеющие закрывающую пару, и не закрывающиеся сами - закрыть. Т.е. те же <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251"> перевести в <meta http-equiv="Content-Type" content="text/html;" charset="windows-1251" />
<img src="..."> в <img src="..." />
Я так понимаю, что задача выполнимая. Но как это сделать? По существующей документации разобраться очень трудно.
<img src="..."> - это если (<.*?\s)(.*?(?<![\/|\/\s])>) и как-то обозначить, что дальше по тексту не встречается $1.*?(?<=[\/|\/\s])> - как-то так...
То тогда менять на $1...[внутренности тега]... /> Во всяком случае такая строка поиска находит теги, не закрывающие сами себя... И в то же время такие вот вещи "<b> some </b>some<b>" (оказывается выделенным всё, что в кавычках). Но как дальше? И как избежать вот этих ошибок. Нужно как-то обозначить, что внутри $1 не должно быть ">" и вообще та закрывающая скобка, которая явно нарисована, должна быть первой закрывающей.
Да, ещё, нужно учесть, что закрывающий тег может быть и не в той же самой строке. А в сложных случаях - вложенность тегов...
И ещё, можно ли как-то указать, что группа должна быть больше, меньше, равно, не больше, не меньше, чем столько-то символов? Не считая, конечно, явного составления из "ровно один любой символ". Могу я для строки AZXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX указав A.*X, указать ещё и длину не больше 15 символов? Хотя здесь ещё просто, а вот для предыдущих упражнений с тегами задавать длину не более 75 символов со всеми параметрами?
Как можно задать строку-исключение? "XXX" не должна входить в "A.*?Z".
Думаю, если подробный разбор этого дела сделать (с пояснениями), то практически с любой степенью сложности регэкспов можно будет справиться. Или есть и более сложные примеры?
(<(?!\/).+?\s(?<!>))(.*?(?<![\/|\/\s])>) находит "<b> some </b>", но не "<b> some </b>some<b>" (без кавычек).
А ещё "<pre><font size=4>".
(<(?!\/).+?[\s>](?<!>))(.*?(?<![\/|\/\s])>) и того хуже.
Пользуюсь ФАРом больше 20 лет © собирательный.
Рекомендую не пытаться объять необъятное (или впихнуть невпихуемое - кому как больше нравится .
Все перечисленное надо разбить на отдельные маленькие задачи.
Например:
1) исправление регистра в открывающих тегах
искать: <[A-Z ]+?=
заменить: \L$0
2) исправление регистра в закрывающих тегах
искать: <\/[A-Z]+?>
заменить: \L$0
3) замена одинарных кавычек на двойные:
искать: ='(\w+)'
заменить: ="$1"
и так далее...
P.S. Насчет ограничения длины для выражения <regexp> - попробуй (?=<regexp>)<.{1,75}>
Все перечисленное надо разбить на отдельные маленькие задачи.
Например:
1) исправление регистра в открывающих тегах
искать: <[A-Z ]+?=
заменить: \L$0
2) исправление регистра в закрывающих тегах
искать: <\/[A-Z]+?>
заменить: \L$0
3) замена одинарных кавычек на двойные:
искать: ='(\w+)'
заменить: ="$1"
и так далее...
P.S. Насчет ограничения длины для выражения <regexp> - попробуй (?=<regexp>)<.{1,75}>
- Centaur
- Posts: 1083
- Joined: Tue 05 Apr, 2005 20:09
- Location: Novosibirsk, Russia
- Been thanked: 2 times
Регулярные выражения — самый слабый из способов задания языков. Не надо хотеть решать ими все задачи обработки текста.
Вышеописанная задача больше похожа на приведение достандартного HTML к формату XHTML или XML. Её решает, например, программа HTML Tidy.
Вышеописанная задача больше похожа на приведение достандартного HTML к формату XHTML или XML. Её решает, например, программа HTML Tidy.
al666 - спасибо. Попробую от этого поплясать.
Centaur - посмотрю и прогу. Мне действительно часто приходится приводить
HTML к XHTML\XML. Но, во-первых: не только. Во-вторых: если это самый слабый
способ задания языков - то что сильней (из универсальных средств)?
К регэкспам я пришёл после программулины HTMLchanger (http://sura.ru/emanovs/)
- мощнейшая вещь для пакетной обработки файлов с довольно простым и слабоватым
синтаксисом. Однако с её помощью я, к примеру, поубирал банеры из сотен
мегабайт документации. Там можно задавать сразу много шаблонов\схем сразу, чего
нельзя в s_and_r\REsearch. А ещё там есть не только подтверждение, но и
возможность редактировать на лету результат замены - в диалоге подтверждения
это предусмотрено. Ну и ещё вкусности.
HTMLchanger'а перестало хватать для моих задач, зато открыл для себя регэкспы.
Которые посложней будут. Вот и хочу разобраться с ними. А проще всего это
сделать на примерах, которые хотелось бы иметь сразу в стандартной поставке.
Готов даже поделиться своим опытом.
Здесь ещё одна задача: многие плугины основаны как раз на сабже. К примеру
TrueTemplate. Не умея читать этот синтаксис хотя бы на уровне любимого языка
программирования, разобраться с плугином сложно - проще снести и забыть.
Centaur - посмотрю и прогу. Мне действительно часто приходится приводить
HTML к XHTML\XML. Но, во-первых: не только. Во-вторых: если это самый слабый
способ задания языков - то что сильней (из универсальных средств)?
К регэкспам я пришёл после программулины HTMLchanger (http://sura.ru/emanovs/)
- мощнейшая вещь для пакетной обработки файлов с довольно простым и слабоватым
синтаксисом. Однако с её помощью я, к примеру, поубирал банеры из сотен
мегабайт документации. Там можно задавать сразу много шаблонов\схем сразу, чего
нельзя в s_and_r\REsearch. А ещё там есть не только подтверждение, но и
возможность редактировать на лету результат замены - в диалоге подтверждения
это предусмотрено. Ну и ещё вкусности.
HTMLchanger'а перестало хватать для моих задач, зато открыл для себя регэкспы.
Которые посложней будут. Вот и хочу разобраться с ними. А проще всего это
сделать на примерах, которые хотелось бы иметь сразу в стандартной поставке.
Готов даже поделиться своим опытом.
Здесь ещё одна задача: многие плугины основаны как раз на сабже. К примеру
TrueTemplate. Не умея читать этот синтаксис хотя бы на уровне любимого языка
программирования, разобраться с плугином сложно - проще снести и забыть.
Пользуюсь ФАРом больше 20 лет © собирательный.
Re: Far 2.0 - regexp
Небольшой вопрос: хочу убрать в файле \N между словами, но оставить там, где он есть после точки или другого знака препинания
Пример:
а вот что подставить в диалог замены, чтобы \N заменилось на пробел, а соседние символы остались неизменными?
Пример:
regexp для поиска сделал такойвсегда\Nмогу
сегодня\Nне
Code: Select all
(\l)\\N(\l)
- WARP ItSelf
- Самый умный
- Posts: 1011
- Joined: Tue 15 Mar, 2005 23:19
- Contact:
Помогите с регулярным выражением.
Задача такая, есть строка с версией (сами знаете чего ). Строка имеет довольно произвольный вид, известно о ней только то, что она содержит числа, точки и буквы. Подходящие строки:
1.0 alpha 1
2.0.0rc2
1.0.0a
1.0.0.5
Задача - попилить эту строку с помощью регулярных выражений так, чтобы на выходе получить 4 числа (если их там есть 4, можно меньше) и все огрызки строк. Точки не нужны.
1.0 alpha 1
2.0.0rc2
1.0.0a
1.0.0.5
Задача - попилить эту строку с помощью регулярных выражений так, чтобы на выходе получить 4 числа (если их там есть 4, можно меньше) и все огрызки строк. Точки не нужны.
Никто не знал, а я...
- HaRT
- Moderator
- Posts: 10869
- Joined: Tue 30 Aug, 2005 17:21
- Has thanked: 221 times
- Been thanked: 358 times
Re: Помогите с регулярным выражением.
В предположении, что строка начинается с цифры, правильно ли я понял, что строка имеет такой вид:
ЦЦ1 ТП БП1 ТП ЦЦ2 ТП БП2 ТП ЦЦ3 ТП БП3 ТП ЦЦ4 ТП БП4,
где
ЦЦ# — цифры
БП# — буквы и подчерки
ТП — точки и пробелы
ЦЦ1 ТП БП1 ТП ЦЦ2 ТП БП2 ТП ЦЦ3 ТП БП3 ТП ЦЦ4 ТП БП4,
где
ЦЦ# — цифры
БП# — буквы и подчерки
ТП — точки и пробелы
Фар есть инструмент, а не нянька. © 2009 DrKnS
-
- Posts: 6840
- Joined: Thu 23 Mar, 2006 21:36
- Location: Israel
- Has thanked: 41 times
- Been thanked: 530 times
Re: Помогите с регулярным выражением.
Code: Select all
(\d+)[\. ]?(\D*)(\d*)[\. ]?(\D*)(\d*)[\. ]?(\D*)(\d*)[\. ]?(\D*)
$2, $4, $6, $8 - аналогично для "огрызков строк", одиночные точки и пробелы - пропускаются.
Re: Помогите с регулярным выражением.
cat <<EOL | perl -MData::Dumper -ne"my @a = grep { not /^(\s+|\.|)$/ } split /(\s+|\.|\d+|\a+)/; print Dumper( \@a )"
1.0 alpha 1
2.0.0rc2
1.0.0a
1.0.0.5
EOL
1.0 alpha 1
2.0.0rc2
1.0.0a
1.0.0.5
EOL
Re: Помогите с регулярным выражением.
на питоне:
ss = ("1.0 alpha 1",
"2.0.0rc2",
"1.0.0a",
"1.0.0.5"
)
import re
for s in ss:
m = re.match(r'(\d+)(\.(\d+))?(\.(\d+))?(\.(\d+))?(.*)', s)
if m:
print m.group(1, 3, 5, 7,
-----------------------
('1', '0', None, None, ' alpha 1')
('2', '0', '0', None, 'rc2')
('1', '0', '0', None, 'a')
('1', '0', '0', '5', '')
ss = ("1.0 alpha 1",
"2.0.0rc2",
"1.0.0a",
"1.0.0.5"
)
import re
for s in ss:
m = re.match(r'(\d+)(\.(\d+))?(\.(\d+))?(\.(\d+))?(.*)', s)
if m:
print m.group(1, 3, 5, 7,
-----------------------
('1', '0', None, None, ' alpha 1')
('2', '0', '0', None, 'rc2')
('1', '0', '0', None, 'a')
('1', '0', '0', '5', '')
- WARP ItSelf
- Самый умный
- Posts: 1011
- Joined: Tue 15 Mar, 2005 23:19
- Contact:
Re: Помогите с регулярным выражением.
Shmuel
Взлетело, похоже. Спасибо.
Всем остальным тоже спасибо, временно отбой, пока работает.
Взлетело, похоже. Спасибо.
Всем остальным тоже спасибо, временно отбой, пока работает.
Никто не знал, а я...
Re: Помогите с регулярным выражением.
На JScript
Code: Select all
var TestStrings = [
'1.0 alpha 1',
' 2.0.0rc2 ',
'1.0.0a',
'1.0 RC 2 10 beta 5'
];
var NumbersRE = /\d+/g;
var OthersRE = /[^\d\.\s][^\d\.]*?(?=[\d\.\s]|$)/g;
function show(a){
if(a==null || a.length==0) return ' not found';
var result = '';
for(var n=0; n<a.length; ++n) result += ' "'+a[n]+'"';
return result;
}
for(var i=0; i<TestStrings.length; ++i){
var s = TestStrings[i];
WScript.echo(
'"'+s+'"\r\n'+
'\r\n'+
' Numbers:'+show(s.match(NumbersRE))+'\r\n'+
' Others:' +show(s.match(OthersRE)) +'\r\n');
}
-
- Posts: 3651
- Joined: Wed 23 Nov, 2005 11:11
- Location: Москва-Питер
- Has thanked: 2 times
- Been thanked: 19 times