Dagens bugg
Följande kod, djupt nere i innanmätet på lagen.nu 1.0-koden, har en bugg, som stått orättad i över tre år (det den ska göra är att stoppa in ett ‘|’-tecken innan ändelser i stil med ‘lagen’, ‘balken’, osv — dvs ‘upphovsrättslagen’ ska bli ‘upphovsrätts|lagen’ — detta av EBNF-tekniska skäl.
fixedindata = re.sub(r'\B(lagens?|balkens?|förordningens?)\b',
r'|\1', self.indata)
Hittar ni felet? Ledtråd — det uppträder bara för en av de tio balkarna, samt för ett mycket litet fåtal lagar och förordningar.
Tags: programmering lagen.nu
februari 8th, 2008 at 00:43
Styggt med svenska tecken. Men det här funkar ju iaf.
>>> print re.sub(r’(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’miljöbalken’)
miljö|balken
februari 8th, 2008 at 12:51
Rätt identifierat, men fel fixat (ledning: hur funkar det för “arbetsmiljölagen”?)
Min lösning blev att tvinga python att förstå att \B inte skulle betrakta svenska bokstäver som word boundaries genom att tala om att jag vill ha en localesensitiv lösning:
import locale
locale.setlocale(locale.LC_ALL,”)
rex = re.compile(r’\B(lagens?|balkens?|förordningens?)\b’, re.LOCALE)
fixedindata = rex.sub(r’|\1′, self.indata)
februari 9th, 2008 at 00:35
Öh… det funkar väl fint för “arbetsmiljölagen”
>>> print re.sub(r’(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’arbetsmiljölagen’)
arbetsmiljö|lagen
Eller missar jag nåt?
februari 9th, 2008 at 01:07
Nej, det är jag som inte kan läsa — din lösning funkar utmärkt även för det fallet. Däremot verkar den även matcha den “lagen” m.fl strängar även när de står fristående, vilket alltså inte är tanken:
>>> re.sub(r’(?! )(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’enligt lagen’)
u’enligt |lagen’
Spontant förstår jag inte varför inte (?!…)-konstruktionen inte gör det jag trodde den skulle göra, men man kan notera att det inte bara är mellanslag som kan utgöra word boundary — andra exempelsträngar som inte ska matcha är u’enligt\nlagen’, u’enligt\xa0lagen’ och u’enligt\tlagen’.
Istället för att själv tänka igenom alla möjliga tecken som utgör word boundaries vill jag utnyttja att nån annan tänkt igenom det i implementationen av \B i pythons regexpmotor. Men det gäller att få den att förstå att “ö” inte är en word boundary.
februari 9th, 2008 at 03:15
Uj, menade (?>> print re.sub(r’(?<!\s)(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’foo\nmiljöbalken.’)
foo
miljö|balken.
Men jag fattar och håller nog nästan med om att det är finare att göra det med word boundaries.
februari 9th, 2008 at 03:16
Uh… wordpress filtrerade bort rätt bra i förra inlägget. Testar igen.
>>> print re.sub(r’(?<!\s)(lagens?|balkens?|förordningens?)\b’, r’|\1′, u’foo\nmiljöbalken.’)
foo
miljö|balken.
april 29th, 2008 at 21:37
“Istället för att själv tänka igenom alla möjliga tecken som utgör word boundaries vill jag utnyttja att nån annan tänkt igenom det i implementationen av \B i pythons regexpmotor.”
Varandes den personen
så vill jag bara påpeka att eftersom du redan använder Unicode för texten så är lösningen att tala om för regexp-motorn att den ska använda Unicode-regler, vilket du gör med ett “(?u)” först i mönstret:
>>> re.sub(r”(?u)\B(lagens?|balkens?|förordningens?)\b”,
r”|\1″, u’arbetsmiljöbalken.’)
u’arbetsmilj\xf6|balken.’
(alternativt använd re.UNICODE istället för re.LOCALE)