Handout
Transkrypt
Handout
Obliczenia Symboliczne I
Przetwarzanie Tekstu
Unicode
>>> s1 = unicode('abcdef')
>>> s2 = u'abcdef'
Unicode
>>> unicode('\x80abc', errors='strict')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode
byte 0x80 in position 0:
ordinal not in range(128)
Unicode
>>> >>> unicode('\x80abc', errors='replace')
u'\ufffdabc'
>>> unicode('\x80abc', errors='ignore')
u'abc'
>>> unichr(40960)
u'\ua000'
>>> ord(u'\ua000')
40960
Unicode
>>> s = u'Was ever feather so lightly blown to
and fro as this multitude?'
>>> s.count('e')
5
>>> s.find('feather')
9
Unicode
>>> s.find('Was\x9f')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeDecodeError: 'ascii' codec can't decode
byte 0x9f in position 3: ordinal not in range(128)
>>> s.find(u'Was\x9f')
-1
Unicode
>>> u = unichr(40960) + u'abcd' + unichr(1972)
>>> u.encode('utf-8')
'\xea\x80\x80abcd\xde\xb4'
>>> u.encode('ascii')
Traceback (most recent call last):
File "<stdin>", line 1, in ?
UnicodeEncodeError: 'ascii' codec can't encode character '\ua000' in
position 0: ordinal not in range(128)
>>> u.encode('ascii', 'replace')
'?abcd?'
>>> u.encode('ascii', 'xmlcharrefreplace')
'ꀀabcd޴'
Unicode
michal@michal-laptop:~$ cat test.py
# -*- coding: utf-8 -*print u"ółążśźóćł"
Unicode
michal@michal-laptop:~$ python test.py
ółążśźóćł
Unicode
michal@michal-laptop:~$ python test.py > wynik
michal@michal-laptop:~$ cat wynik
Traceback (most recent call last):
File "test.py", line 3, in <module>
print u"ółążśźóćł"
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-8:
ordinal not in range(128)
Unicode
# -*- coding: utf-8 -*import sys
import codecs
print sys.stdout.encoding
#sys.stdout.encodin==None: ... to jest zmienna typu readonly
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
print u"ółążśźóćł"
Unicode
uni = u"Hello\u001A\u0BC3\u1451\U0001D10CUnicode"
utf8_string = uni.encode('utf-8')
# naively convert back to Unicode
uni = unicode(utf8_string)
Unicode
Traceback (most recent call last):
File "t6.py", line 5, in ?
uni = unicode(utf8_string)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe0
in position 6: ordinal not in range(128)
Unicode
uni = u"Hello\u001A\u0BC3\u1451\U0001D10CUnicode"
utf8_string = uni.encode('utf-8')
# have to decode with the same codec the encoder used!
uni = unicode(utf8_string,'utf-8')
print "Back from UTF-8: ",repr(uni)
Wyrażenia regularne
Some people, when confronted with a problem, think "I
know, I'll use regular expressions." Now they have two
problems.
-- Jamie Zawinski, '<alt.religion.emacs>' (08/12/1997)
Wyrażenia regularne
[ ... ] - zakres znaków („klasa”)
^ - operator dopełnienia mnogościowego
. - dowolny znak ale nie koniec linii
\d – cyfry – odpowiada [0-9]
\D – nie-cyfry – odpowiada [^0-9]
\s – biały znak – odpowiada [ \t\n\r\f\v]
\S – nie-biały znak – odpowiada [^ \t\n\r\f\v].
\w – znak alfanumeryczny – odpowiada [a-zA-Z0-9_]
\W – znak niealfanumeryczny – odpowiada [^a-zA-Z0-9_]
Wyrażenia regularne
| - „lub” ab|bc
^ - oznaczenie początku linii ^From:
$ - oznaczenie końca linii End.$
\A – początek
\Z – koniec
\b – granica słowa (! - uwaga na backspace)
>>> p = re.compile(r'\bclass\b')
>>> p = re.compile('\bclass\b')
\B negacja \b
Wyrażenia regularne
* - powielenie 0 lub więcej razy („gwiazdka Kleene'a”)
>>> p = re.compile('(ab)*')
>>> print p.match('ababababab').span()
(0, 10)
{min,max} a/{1,3}b -> "a/b", "a//b", and "a///b".
+ - „Plus Kleene'a” - 1 lub więcej
? - 0 lub 1 razy
Wyrażenia regularne
Niezachłanne dopasowania
*?
+?
??
{m,n}?
s = '<html><head><title>Title</title>'
print re.match('<.*>', s).group()
<html><head><title>Title</title>
print re.match('<.*?>', s).group()
<html>
Grupowanie
Grupowanie
>>> p = re.compile('(a(b)c)d')
>>> m = p.match('abcd')
>>> m.group(0)
'abcd'
>>> m.group(1)
'abc'
>>> m.group(2)
'b'
Grupowanie
Nie przechwytująca grupa (?:foo)
re.match("([abc])+", "abc").groups()
('c',)
re.match("(?:[abc])+", "abc").groups()
()
Nazwana grupa (?P<name>...)
>>> p = re.compile(r'(?P<word>\b\w+\b)')
>>> m = p.search( '(((( Lots of punctuation )))' )
>>> m.group('word')
'Lots'
Powielenie (?P=<name>)
>>> p = re.compile(r'(?P<word>\b\w+)\s+(?P=word)')
Grupowanie
Lookahead pozytywne (?=...)
Lookahead negatywne
Wszystkie pliki z wyjątkiem bat i exe
.*[.](?!bat$|exe$).*$
Negative look behind (?<!regex) – dopasuj jeśli zaraz
poprzedzającym nie był regex
Positive look behind (?<=regex)
Warunkowe wyrażenia
Etc ....
Wyrażenia regularne
>>> import re
>>> p = re.compile('ab*')
>>> print p
<re.RegexObject instance at 80b4150>
>>> p = re.compile('ab*', re.IGNORECASE)
Wyrażenia regularne
Cel: \section
Wyrażenie: \\section
Stała łańcuchowa: \\\\section
Notacja „raw string”:
„ab*” → r”ab*”
„\\\\section” → r”\\section”
„\\w+\\s+\\1” → r”\w+\s+\1”
Wyrażenia regularne
>>> import re
>>> p = re.compile('[a-z]+')
>>> p
<_sre.SRE_Pattern object at 80c3c28>
Wyrażenia regularne
match()
Szuka dopasowania na początku napisu
search()
Szuka dopasowania, także w środku
findall(), finditer()
Szuka dopasowań, zwraca, odpowiednio, listę lub
iterator
Wyrażenia regularne
>>> print p.match("")
None
>>> print m = p.match( 'ala')
<_sre.SRE_Match object at 80c4f68>
Wyrażenia regularne
m.group()
Wypisuje dopasowany napis
m.start(), m.end(), m.span()
Podaje indeksy miejsca dopasowanego
Wyrażenia regularne
>>> p = re.compile('\d+')
>>> iterator = p.finditer('12 drummers drumming, 11 ... 10 ...')
>>> for match in iterator:
...
print match.span()
...
(0, 2)
(22, 24)
(29, 31)
Funkcje modułu
re.match( regex, string )
re.search (regex, string )
re.sub() ...
etc.
Flagi compile
re.compile( regex, flags)
DOTALL , S
re.compile(„.*”, re.S)
IGNORECASE, I
LOCALE, L
MULTILINE, M
VERBOSE, X
re.compile( „a*”, re.I | re.M )
re.compile(„(?xm)a*”)
Wyrażenia regularne
re.VERBOSE
pat = re.compile(r"\s*(?P<header>[^:]+)\s*:(?P<value>.*?)\s*$")
Wyrażenia regularne
pat = re.compile(r"""
\s*
# Skip leading whitespace
(?P<header>[^:]+) # Header name
\s* :
# Whitespace, and a colon
(?P<value>.*?)
# The header's value -- *? used to
# lose the following trailing whitespace
\s*$
""", re.VERBOSE)
# Trailing whitespace to end-of-line
Podstawienie
>>> 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'
>>> p = re.compile('x*')
>>> p.sub('-', 'abxd')
'-a-b-d-'
Podstawienie
Podstawienie z dopasowaniem
>>> p = re.compile('section{ ( [^}]* ) }', re.VERBOSE)
>>> p.sub(r'subsection{\1}','section{First}
section{second}')
'subsection{First} subsection{second}'
>>> p = re.compile('section{ (?P<name> [^}]* ) }', re.VERBOSE)
>>> p.sub(r'subsection{\1}','section{First}')
'subsection{First}'
>>> p.sub(r'subsection{\g<1>}','section{First}')
'subsection{First}'
>>> p.sub(r'subsection{\g<name>}','section{First}')
'subsection{First}'
Podstawienie
>>> def repl(m):
... inner_word = list(m.group(2))
... random.shuffle(inner_word)
... return m.group(1) + "".join(inner_word) + m.group(3)
>>> text = "Professor Abdolmalek, please report your absences
promptly."
>>> re.sub("(\w)(\w+)(\w)", repl, text)
'Poefsrosr Aealmlobdk, pslaee reorpt your abnseces plmrptoy.'
Paragraf w lewo
#flush left
from re import findall,sub
indent = lambda s: reduce(min,map(len,findall('(?m)^ *(?=\S)',s)))
flush_left = lambda s: sub('(?m)^ {%d}' % indent(s),'',s)
print flush_left(sys.stdin.read())
Usuwanie duplikatów
import sys, re, glob
for pat in sys.argv[1:]:
for file in glob.glob(pat):
newfile = 1
for para in open(file).read().split('\n\n'):
dups = re.findall(r'(?m)(^.*(\b\w+\b)\s*\b\2\b.*$)', para)
if dups:
if newfile:
print '%s\n%s\n' % ('-'*70,file)
newfile = 0
for dup in dups:
print '[%s] -->' % dup[1], dup[0]