Search     or:     and:
 LINUX 
 Language 
 Kernel 
 Package 
 Book 
 Test 
 OS 
 Forum 
 iakovlev.org 
 Languages
 С
 GNU С Library 
 Qt 
 STL 
 Threads 
 C++ 
 Samples 
 stanford.edu 
 ANSI C
 Libs
 LD
 Socket
 Pusher
 Pipes
 Encryption
 Plugin
 Inter-Process
 Errors
 Deep C Secrets
 C + UNIX
 Linked Lists / Trees
 Asm
 Perl
 Python
 Shell
 Erlang
 Go
 Rust
 Алгоритмы
NEWS
Последние статьи :
  Тренажёр 16.01   
  Эльбрус 05.12   
  Алгоритмы 12.04   
  Rust 07.11   
  Go 25.12   
  EXT4 10.11   
  FS benchmark 15.09   
  Сетунь 23.07   
  Trees 25.06   
  Apache 03.02   
 
TOP 20
 MINIX...3057 
 Solaris...2933 
 LD...2904 
 Linux Kernel 2.6...2470 
 William Gropp...2180 
 Rodriguez 6...2012 
 C++ Templates 3...1945 
 Trees...1937 
 Kamran Husain...1866 
 Secure Programming for Li...1792 
 Максвелл 5...1710 
 DevFS...1694 
 Part 3...1684 
 Stein-MacEachern-> Час...1632 
 Go Web ...1624 
 Ethreal 4...1618 
 Arrays...1607 
 Стивенс 9...1603 
 Максвелл 1...1592 
 FAQ...1538 
 
  01.01.2024 : 3621733 посещений 

iakovlev.org

Python Tutorial 5

1 Regular Expression

Стандартный модуль re добавлен , начиная с версии 1.5. Для более ранних версий работает модуль regex .

Рассмотрим пример - пусть у нас есть регулярное выражение test , оно будет полностью соответствовать строке "test" . Этот шаблон состоит из обычных символов . Но для некоторых символов правила соответствия не действуют .

Вот полный список этих метасимволов :

 . ^ $ * + ? { [ ] \ | ( )
 

Рассмотрим комбинацию из квадратных скобок "[" и "]". Они используются для определения символьного класса-шаблона . Символы внутри такого класса можно задавать индивидуально или задать в диапазоне с разделителем "-". Например, [abc] будет соответствовать любому из символов "a", "b", или "c"; или что то же самое [a-c] . Если нужно задать нижний регистр , это будет [a-z].

Метасимволы не входят внутрь такого класса-шаблона. Хотя , если метасимвол входит в класс-шаблон , как в случае с [akm$] , то он будет соответствовать любому из символов "a", "k", "m", или "$" .

Для исключения какого-то символа из класса-шаблона нужно использовать "^" . Например , [^5] будет соответствовать любому символу , кроме "5".

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

\d
десятичная цифра; эквивалентно классу [0-9].

\D
не-цифра; соответствует классу [^0-9].

\s
пробел; соответствует классу [ \t\n\r\f\v].

\S
не-пробел; соответствует [^ \t\n\r\f\v].

\w
буквенно-числовой символ; соответствует [a-zA-Z0-9_].

\W
не-буквенно-числовой символ; соответствует [^a-zA-Z0-9_].

Эти последовательности могут включаться в шаблон , например [\s,.] соответствует любому пробелу , или "," или ".".

И наконец последний метасимвол в этой серии - это точка .. Она соответствеут всему , окромя символу новой строки .

Другим важным метасимволом для определения повторов является звездочка * . Например , шаблон ca*t будет соответствовать "ct" (0 "a" символов), "cat" (1 "a"), "caaat" (3 "a" символов), и так далее.

В качестве примера рассмотрим шаблон a[bcd]*b и поисковую строку "abcbd". Ниже представлена таблица соответствий :

Step  Matched  Explanation 
1 a The a in the RE matches.
2 abcbd The engine matches [bcd]*, going as far as it can, which is to the end of the string.
3 Failure The engine tries to match b, but the current position is at the end of the string, so it fails.
4 abcb Back up, so that [bcd]* matches one less character.
5 Failure Try b again, but the current position is at the last character, which is a "d".
6 abc Back up again, so that [bcd]* is only matching "bc".
6 abcb Try b again. This time but the character at the current position is "b", so it succeeds.

Другим символом повтора является плюс +. Разница между * и + в том , что * соответствует нулю или больше раз, в то время как + требует хотя бы одного совпадения. Например , ca+t будет соответствовать "cat" (1 "a"), "caaat" (3 "a"'s), но не соответствует "ct".

Еще одним метасимволом повтора является ?, соответсвующий нулю/одному попаданию . Например, home-?brew соответствует как "homebrew" , так и "home-brew".

Конструкция составного квалификатора имеет вид {m,n}, где m и n десятичные числа . Это означает , что символ должен повторяться не менее m раз , но и не более n. Например, a/{1,3}b будет соответствовать "a/b", "a//b", и "a///b", но не "ab", в котором нет слэша , или не "a////b", в котором 4 слэша .

Кстати говоря , {0,} - то же самое , что и звезда *, {1,} - эквивалентно плюсу +, и {0,1} - то же самое , что и вопрос ?.

Компиляция регулярных выражений

Регулярные выражения компилируются в RegexObject , который имеет методы поиска шаблонов или выполнения строковых операций .

 >>> import re
 >>> p = re.compile('ab*')
 >>> print p
 <re.RegexObject instance at 80b4150>
 

re-модуль - модуль , написанный на С и включенный в питон аналогично модулям socket or zlib.

RegexObject имеет несколько методов и атрибутов . Наиболее важные из них :

Method/Attribute  Назначение 
match() Соответствие шаблону с начала строки
search() Соответствие шаблону с любой позиции строки
findall() Нахождение всех соответствий , возвращает список
finditer() Нахождение всех соответствий , возвращает итератор

match() и search() возвращают None , если соответствие не найдено . В противном случае возвращается инстанс MatchObject , включающий информацию о соответствии: позицию , подстроку, и т.д.

На http://kodos.sourceforge.net можно найти тулзу для интерактивной отладки .

Пример:

 Python 2.2.2 (#1, Feb 10 2003, 12:57:01)
 >>> import re
 >>> p = re.compile('[a-z]+')
 >>> p
 <_sre.SRE_Pattern object at 80c3c28>
 

Теперь попробуем найти соответствие для пустой строки - результат None :

 >>> p.match("")
 >>> print p.match("")
 None
 

Теперь получим положительный результат и сохраним его в переменной :

 >>> m = p.match( 'tempo')
 >>> print m
 <_sre.SRE_Match object at 80c4f68>
 

Инстанс MatchObject имеет несколько методов и атрибутов :

Method/Attribute  Назначение 
group() Возвращает строку , соответствующую шаблону
start() Возвращает стартовую позицию совпадения
end() Возвращает конечную позицию совпадения
span() Возвращает пару позиций

Попробуем:

 >>> m.group()
 'tempo'
 >>> m.start(), m.end()
 (0, 5)
 >>> m.span()
 (0, 5)
 

 >>> print p.match('::: message')
 None
 >>> m = p.search('::: message') ; print m
 <re.MatchObject instance at 80c9650>
 >>> m.group()
 'message'
 >>> m.span()
 (4, 11)
 

В программах обычно инстанс MatchObject сохраняют в переменной , после чего проверяют :

 p = re.compile( ... )
 m = p.match( 'string goes here' )
 if m:
     print 'Match found: ', m.group()
 else:
     print 'No match'
 

findall() возвращает список совпадений :

 >>> p = re.compile('\d+')
 >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
 ['12', '11', '10']
 

finditer() возвращает последовательность MatchObject-инстансов как итератор :

 >>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
 >>> iterator
 <callable-iterator object at 0x401833ac>
 >>> for match in iterator:
 ...     print match.span()
 ...
 (0, 2)
 (22, 24)
 (29, 31)
 

Вообще нет особой необходимости создавать инстанс RegexObject , для этого модуль re имеет набор высокоуровневых функций match(), search(), sub(), и т.д.

 >>> print re.match(r'From\s+', 'Fromage amk')
 None
 >>> re.match(r'From\s+', 'From amk Thu May 14 19:12:10 1998')
 <re.MatchObject instance at 80c5978>
 

Использование инстанса RegexObject может стать актуальным , если регулярные выражения используются очень часто . В этом случае компиляция может быть собрана в одном месте :

 ref = re.compile( ... )
 entityref = re.compile( ... )
 charref = re.compile( ... )
 starttagopen = re.compile( ... )
 

Опции компиляции

Некоторые опции компиляции :

Flag  Значение 
DOTALL, S Соответствие любому символу , включая символ новой строки
IGNORECASE, I Делает различимыми регистры
LOCALE, L Локальное соответствие
MULTILINE, M Многострочное соответствие
VERBOSE, X Детализация поискового шаблона

IGNORECASE
Например, [A-Z] при таком флаге будет соответствовать и Spam , и "spam", и "spAM".

LOCALE
Позволяет работать с различными языковыми локалями.

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

 charref = re.compile(r"""
  &[#]		     # Start of a numeric entity reference
  (
    [0-9]+[^0-9]      # Decimal form
    | 0[0-7]+[^0-7]   # Octal form
    | x[0-9a-fA-F]+[^0-9a-fA-F] # Hexadecimal form
  )
 """, re.VERBOSE)
 

Без verbose , RE выглядело бы так :

 charref = re.compile("&#([0-9]+[^0-9]"
                      "|0[0-7]+[^0-7]"
                      "|x[0-9a-fA-F]+[^0-9a-fA-F])")
 

Еще несколько метасимволов

|
Символ вертикальный слэш выполняет роль оператора ``or'' . Если A и B - регулярные выражения, A|B будет соответствовать любой строке , соответствующей "A" или "B". Crow|Servo будет соответствовать "Crow" или "Servo", но не "Cro", "w" , "S", или "ervo".

^
Соответствует началу строки :

 >>> print re.search('^From', 'From Here to Eternity')
 <re.MatchObject instance at 80c1520>
 >>> print re.search('^From', 'Reciting From Memory')
 None
 

$
Соответствует концу строки :

 >>> print re.search('}$', '{block}')
 <re.MatchObject instance at 80adfa8>
 >>> print re.search('}$', '{block} ')
 None
 >>> print re.search('}$', '{block}\n')
 <re.MatchObject instance at 80adfa8>
 

\b
Разделитель слов .

Cледующий пример соответствует "class" для слова целиком и не соответствует , если находится внутри другого слова :

 >>> p = re.compile(r'\bclass\b')
 >>> print p.search('no class at all')
 <re.MatchObject instance at 80c8f28>
 >>> print p.search('the declassified algorithm')
 None
 >>> print p.search('one subclass is')
 None
 

Или так :

 >>> p = re.compile('\bclass\b')
 >>> print p.search('no class at all')
 None
 >>> print p.search('\b' + 'class' + '\b')
 <re.MatchObject instance at 80c3ee0>
 

Группировка

Группировка маркируется с помощью скобок "(", ")". Скобки имеют примерно такое же значение , что и в математических выражениях . Например , можно повторить содержание внутри группы с помощью метасимволов *, +, ?, или {m,n}. Например :

 >>> p = re.compile('(ab)*')
 >>> print p.match('ababababab').span()
 (0, 10)
 

 >>> p = re.compile('(a)b')
 >>> m = p.match('ab')
 >>> m.group()
 'ab'
 >>> m.group(0)
 'ab'
 

Группировка может быть вложенной :

 >>> p = re.compile('(a(b)c)d')
 >>> m = p.match('abcd')
 >>> m.group(0)
 'abcd'
 >>> m.group(1)
 'abc'
 >>> m.group(2)
 'b'
 

group() может иметь в качестве параметров группу чисел и вернуть массив :

 >>> m.group(2,1,2)
 ('b', 'abc', 'b')
 

groups() возвращает массив строк для всех подгрупп .

 >>> m.groups()
 ('abc', 'b')
 

В следующем примере находятся двойные слова в строке :

 >>> p = re.compile(r'(\b\w+)\s+\1')
 >>> p.search('Paris in the the spring').group()
 'the the'
 

Следующий шаблон находит файлы , имена которых имеют расширение .bat или .exe :
.*[.](?!bat$|exe$).*$

Для модификации поисковых строк используются методы обьекта RegexObject :

Method/Attribute  Назначение 
split() Разбиение строки на список
sub() Поиск и замена подстрок
subn() То же , что и sub(), но возвращает новую строку

Примеры работы split :

 >>> p = re.compile(r'\W+')
 >>> p.split('This is a test, short and sweet, of split().')
 ['This', 'is', 'a', 'test', 'short', 'and', 'sweet', 'of', 'split', '']
 >>> p.split('This is a test, short and sweet, of split().', 3)
 ['This', 'is', 'a', 'test, short and sweet, of split().']
 

Другой пример :

 >>> p = re.compile(r'\W+')
 >>> p2 = re.compile(r'(\W+)')
 >>> p.split('This... is a test.')
 ['This', 'is', 'a', 'test', '']
 >>> p2.split('This... is a test.')
 ['This', '... ', 'is', ' ', 'a', ' ', 'test', '.', '']
 

Другая версия :

 >>> re.split('[\W]+', 'Words, words, words.')
 ['Words', 'words', 'words', '']
 >>> re.split('([\W]+)', 'Words, words, words.')
 ['Words', ', ', 'words', ', ', 'words', '.', '']
 >>> re.split('[\W]+', 'Words, words, words.', 1)
 ['Words', 'words, words.']
 

Search and Replace

Поиск и замена выполняются с помощью встроенной функции sub() .

В следующем примере цвет заменяется на colour столько раз , на сколько указывает 2-й аргумент :

 >>> p = re.compile( '(blue|white|red)')
 >>> p.sub( 'colour', 'blue socks and red shoes')
 'colour socks and colour shoes'
 >>> p.sub( 'colour', 'blue socks and red shoes', count=1)
 'colour socks and red shoes'
 

Пример для subn() :

 >>> p = re.compile( '(blue|white|red)')
 >>> p.subn( 'colour', 'blue socks and red shoes')
 ('colour socks and colour shoes', 2)
 >>> p.subn( 'colour', 'no colours at all')
 ('no colours at all', 0)
 

В следующем примере "section" меняется на "subsection":

 >>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
 >>> p.sub(r'subsection{\1}','section{First} section{second}')
 'subsection{First} subsection{second}'
 

Замещаемое выражение может быть функцией :

 >>> def hexrepl( match ):
 ...     "Return the hex string for a decimal number"
 ...     value = int( match.group() )
 ...     return hex(value)
 ...
 >>> p = re.compile(r'\d+')
 >>> p.sub(hexrepl, 'Call 65490 for printing, 49152 for user code.')
 'Call 0xffd2 for printing, 0xc000 for user code.'
 
Оставьте свой комментарий !

Ваше имя:
Комментарий:
Оба поля являются обязательными

 Автор  Комментарий к данной статье
Юрий
  Здесь написано: 

findall() возвращает список совпадений :

 >>> p = re.compile('d+')
 >>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
 ['12', '11', '10']
 

А если так:

p = re.compile('d(d)')
>>> p.findall('12 drummers drumming, 11 pipers piping, 10 lords a-leaping')
['2', '1', '0']

findall() возвращает только группы. А как все-таки получить все совпадения ?
2007-07-23 18:57:09