Ĉapitro 7 - Skemo Matching kun Regulaj Esprimoj
Subtenu la Aŭtoro: Aĉeti la libron sur Amazono aŭ
la libro / ebook pakaĵo rekte Neniu amelo Gazetaro .
Legi la aŭtora aliaj liberaj Python libroj:
Skemo Matching kun Regulaj Esprimoj
Vi povas esti konata kun serĉanta tekston premante CTRL -F kaj tajpadon en la vortoj vi estas serĉanta. Regulaj esprimoj iri unu paŝon pli: Ili permesas vin specifi bildon de teksto al serĉi.
Vi eble ne scias negoco la ĝusta telefonnumero, sed se vi loĝas en
Usono aŭ Kanado, vi scias estos tri ciferoj, sekvitaj per streketo, kaj
tiam kvar pli ciferoj (kaj laŭvole, tri-cifera prefijo ĉe la komenco). Jen kiel vi, kiel homo, scias telefonnumero kiam vi vidos: 415-555-1234 estas telefonnumero, sed 4.155.551.234 ne.
Regulaj esprimoj estas helpema, sed ne multaj ne-programistoj scias pri
ili eĉ se plej modernaj teksto redaktiloj kaj dokumentoredaktiloj,
ekzemple Microsoft Word aŭ OpenOffice, havas trovi trovu-kaj-anstataŭigi
trajtoj kiuj povas serĉo bazita sur regulaj esprimoj. Regulaj esprimoj estas grandega tempo-ŝparantoj, ne nur por programaro uzantoj sed ankaŭ por programistoj. Fakte, tech verkisto Cory Doctorow argumentas ke eĉ antaŭ instrui programadon, ni instruos regulajn esprimojn:
"Sciante [regulesprimoj] povas signifi la diferencon inter solvanta problemon en 3 paŝoj kaj solvi ĝin en 3.000 ŝtupoj. Kiam vi estas nerd, vi forgesas, ke la problemoj vi solvas kun paro keystrokes povas preni aliajn homojn dum teda, eraro-inklina verkon slog tra. "[ 1 ]
En ĉi tiu ĉapitro, vi komencos per skribanta programon por trovi teksto ŝablonoj sen uzi regulajn esprimojn kaj tiam vidi kiel uzi regulajn esprimojn por fari la kodon multe malpli ŝvela.
Mi montros al vi bazajn trafaj kun regulaj esprimoj kaj tiam movi sur
al iu pli potenca karakterizaĵoj, kiel ekzemple ĉeno anstataŭo kaj krei
vian propran karakteron klasoj. Fine, fine de la ĉapitro, vi skribis programon kiu povas aŭtomate ĉerpi telefonnumerojn kaj retadresojn de bloko de teksto.
Trovante Ŝablonoj de Teksto Sen Regulaj Esprimoj
Diru vi volas trovi telefonnumero en ĉeno. Vi konas la mastron: tri nombroj, streketo, tri ciferoj, streketo, kaj kvar nombroj. Jen ekzemplo: 415-555-4242.
Ni uzi funkcio nomita
isPhoneNumber()
por kontroli ĉu kordo egalas tiun skemon, redonante ambaŭ True
aŭ False
. Malfermi novan dosieron redaktanto fenestro kaj eniri la sekvan kodon: tiam savi la dosiero isPhoneNumber.py: def isPhoneNumber (teksto): ❶ se len (teksto)! = 12: revenu Falsaj por i en gamo (0, 3): ❷ se ne tekston [i] .isdecimal (): revenu Falsaj ❸ se teksto [3]! = '-': revenu Falsaj por i en gamo (4, 7): ❹ se ne tekston [i] .isdecimal (): revenu Falsaj ❺ se teksto [7]! = '-': revenu Falsaj por i en gamo (8, 12): ❻ se ne tekston [i] .isdecimal (): revenu Falsaj ❼ revenos Vera print ( '415-555-4242 Estas telefonnumero:') print (isPhoneNumber ( '415-555-4242')) print ( 'Moshi Moshi estas telefonnumero:') print (isPhoneNumber ( 'Moshi Moshi'))
Kiam tiu programo kuras, la eligo aspektas jene:
415-555-4242 Estas telefonnumero: veraj Moshi Moshi estas telefonnumero: falsa
La
isPhoneNumber()
funkcio havas kodon kiu faras plurajn kontrolojn por vidi ĉu la ĉeno en text
estas valida telefonnumero. Se iu el tiuj kontroloj malsukcesos, la funkcio redonas False
. Unue la kodon kontrolas ke la ŝnuro estas ekzakte 12 karakteroj ❶. Tiam kontrolas ke la prefijo (te la unuajn tri karakterojn en text
) konsistas nur nombraj karakteroj ❷.
La resto de la funkcio kontrolas ke la ŝnuro sekvas la skemon de
telefonnumero: la nombro devas havi la unuan streketo post la prefijo ❸,
tri pli nombraj karakteroj ❹, tiam alia streketo ❺, kaj fine kvar pli
numeroj ❻. Se la programo ekzekuto sukcesas preteriri ĉiujn kontrolojn, ĝi revenas True
❼.
Nomante
isPhoneNumber()
kun la argumento '415-555-4242'
revenos True
. Nomante isPhoneNumber()
kun 'Moshi moshi'
revenos False
; la unua provo malsukcesas ĉar 'Moshi moshi'
ne 12 signojn longa.
Vi devus aldoni eĉ pli kodo trovi tiun padronon de teksto en pli granda ĉeno. Anstataŭi la lastaj kvar
print()
funkcio alvokoj en isPhoneNumber.py kun la sekvaj: mesaĝo = 'Nomu min ĉe 415-555-1011 morgaŭ. 415-555-9999 mia oficejo. por i en gamo (len (mesaĝo)): ❶ bloko = mesaĝo [i: i + 12] ❷ se isPhoneNumber (chunk): print ( 'Telefonnumero trovis:' + bloko) print ( 'Donacu')
Kiam tiu programo kuras, la eligo aspektos tiel ĉi:
Telefonnumero trovis: 415-555-1011 Telefonnumero trovis: 415-555-9999 farita
Sur ĉiu ripeto de la
for
buklo, nova bloko de 12 karakteroj de message
estas atribuita al la variablo chunk
❶. Ekzemple, sur la unua ripeto, i
estas 0
, kaj chunk
estas atribuita message[0:12]
(tio estas, la ĉeno 'Call me at 4'
). Sur la venonta ripeto, i
estas 1
, kaj chunk
estas atribuita message[1:13]
(la kordo 'all me at 41'
).
Sekvinberoj
chunk
al isPhoneNumber()
por vidi ĉu ĝi egalas la telefonnumero padrono ❷, kaj se jes, vi presi la bloko.
Daŭre buklo tra
message
, kaj eventuale la 12 karakteroj en chunk
estos telefonnumero. La ciklo iras tra la tuta ĉeno, provante ĉiun 12-karaktero peco kaj presi ajnan chunk
trovas ke kontentigas isPhoneNumber()
. Iam ni faris iranta tra message
, ni presi Done
.
Dum la ĉenon en
message
estas mallonga en ĉi tiu ekzemplo, ĝi povus esti milionoj da karakteroj longe kaj la programo ankoraŭ kuris en malpli ol dua.
Simila programo kiu trovas telefonnumerojn uzante regulaj esprimoj
ankaŭ kuras en malpli ol sekundo, sed regulesprimoj fari rapidan skribi
tiujn programojn. Trovante Ŝablonoj de Teksto kun Regulaj Esprimoj
La antaŭa telefonnumero-trovo programo funkcias, sed ĝi uzas multan kodon fari ion limigita: la
isPhoneNumber()
funkcio estas 17 linioj sed povas trovi nur unu modelon de telefonnumerojn. Kio pri telefonnumero formatita kiel 415.555.4242 aŭ (415) 555-4242? Kio se la telefonnumero havis etendo, kiel 415-555-4242 x99? La isPhoneNumber()
funkcio malsukcesus validigi ilin. Vi povus aldoni ankoraŭ pli kodo por tiuj aldonaj ŝablonoj, sed ekzistas pli facila maniero.
Regulesprimoj, nomita regexes mallonge, estas priskriboj kiel ekzemplo de teksto. Ekzemple,
\d
en regex starejoj por cifero karaktero-tio estas, ajna ununura numeralo 0 ĝis 9. La regex \d\d\d-\d\d\d-\d\d\d\d
estas uzita de Python parigi la sama teksto la antaŭa isPhoneNumber()
funkcio faris: ŝnuro de tri numeroj, streketo, tri pli nombroj, alia streketo, kaj kvar nombroj. Ajna alia ĉeno ne kongruas al la \d\d\d-\d\d\d-\d\d \d\d
regex.
Sed regulesprimoj povas esti multe pli kompleksa. Ekzemple, aldonante
3
en bukla krampoj ( {3}
) post padrono estas kiel diri, "Trafu tiu padrono trifoje." Do la iomete pli mallonga regex \d{3}-\d{3}-\d{4}
ankaŭ egalas la ĝustan telefonnumero formato. Kreado Regex Objektoj
Ĉiuj regex funkcioj en Python estas en la
re
modulo. Eniri la sekva en la interaga ŝelo importi ĉi modulo: >>> Import re
noto
Plejparto de la ekzemploj kiuj sekvas en ĉi ĉapitro postulos la
re
modulo, tiel memoras por importi ĝin komence de ajna skripto vi skribas aŭ ajna tempo vi restartigu sencela. Alie vi ricevos NameError: name 're' is not defined
erarmesaĝon.
Pasante kordo valoro reprezentanta vian regulan esprimon por
re.compile()
redonas Regex
padrono objekto (aŭ simple, Regex
objekto).
Krei
Regex
objekto kiu egalas la telefonnumero padrono, eniri la sekva en la interaga ŝelo. (Memoru ke \d
signifas "cifero karaktero" kaj \d\d\d-\d\d\d-\d\d\d\d
estas la regula esprimo por la korekta telefonnumero ŝablono.) >>> PhoneNumRegex = re.compile (r '\ d \ d \ d- \ d \ d \ d- \ d \ d \ d \ d')
Nun la
phoneNumRegex
variablo enhavas Regex
objekto. Egalante Regex Objektoj
A
Regex
objekto search()
metodo serĉas la kordo estas pasita por ajna matĉojn por la regex. La search()
metodo revenos None
se la regex padrono ne estas trovita en la ĉeno. Se la padrono estas trovita, la search()
metodo revenas Match
objekto. Match
objektoj havas group()
metodo kiu revenos la fakta kongruis tekston de la traserĉis ŝnuro. (Mi klarigos grupoj baldaŭ.) Ekzemple, tajpu la sekvajn en la interaga konko: >>> PhoneNumRegex = re.compile (r '\ d \ d \ d- \ d \ d \ d- \ d \ d \ d \ d') >>> Mo = phoneNumRegex.search (Mia nombro estas 415-555-4242. ') >>> Print ( 'Telefonnumero trovis:' + mo.group ()) Telefonnumero trovis: 415-555-4242
La
mo
variablo nomiĝas nur gentnomo uzi por Match
objektoj. Tiu ekzemplo povus ŝajnas komplika komence, sed ĝi estas multe pli mallonga ol la antaŭaj isPhoneNumber.py programo kaj faras la samon.
Tie, ni pasas nian dezirata padrono al
re.compile()
kaj stoki la rezultan Regex
objekto en phoneNumRegex
. Tiam ni nomas search()
sur phoneNumRegex
kaj enirpermesilo search()
la kordoj ni volas serĉi matĉo. La rezulto de la serĉo prenas stokitaj en la variablo mo
. En ĉi tiu ekzemplo, ni scias, ke nia mastro estos trovitaj en la ĉeno, do ni scias ke Match
objekto estos reveninta. Sciante ke mo
enhavas Match
objekto kaj ne la nula valoro None
, ni povas nomi group()
sur mo
redoni la matĉo. Skribi mo.group()
ene nia print komunikaĵo montras la tuta matĉo, 415-555-4242
. Revizio de Regula Esprimo Matching
Dum estas pluraj paŝoj al uzante regulaj esprimoj en Python, ĉiu paŝo estas sufiĉe simpla.
- Importi la regex modulo kun
import re
. - Krei
Regex
objekto kun lare.compile()
funkcio. (Memoru uzi krudan ŝnuro.) - Pasas la kordo vi volas serĉi en la
Regex
objektosearch()
metodo. Ĉi resendasMatch
objekto. - Voku la
Match
objektogroup()
metodon redoni kordo de la fakta kongruis tekston.
noto
Dum
mi kuraĝigas vin por eniri la ekzemplon kodon en la interaga ŝelo, vi
ankaŭ devus uzi ttt-bazita regula esprimo testers, kiu povas montri vin
ĝuste kiel regex matĉojn teksteron ke vi eniru. Mi rekomendas la testanto ĉe http://regexpal.com/ .
Pli Skemo Matching kun Regulaj Esprimoj
Nun ke vi scias la bazajn paŝojn por krei kaj trovi regula esprimo
celoj kun Python, vi pretas provi iuj de liaj pli potencaj mastro-trafaj
kapabloj.
Kolektante kun paréntesis
Diru vi volas apartigi la prefijo de la resto de la telefonnumero. Aldonante krampojn kreos grupojn en la regex:
(\d\d\d)-(\d\d\d-\d\d\d\d)
. Tiam vi povas uzi la group()
matĉo objekto metodo ekpreni la trafa teksto el nur unu grupo.
La unua aro de parentezoj en regex ŝnuro estos grupo
1
. La dua aro estos grupo 2
. Aprobante la entjero 1
aŭ 2
al la group()
matĉo objekto metodo, Vi povas ekpreni malsamaj partoj de la kongruis tekston. Pasante 0
aŭ nenion al la group()
metodo revenos la tutan kongruis tekston. Eniri la sekva en la interaga konko: >>> PhoneNumRegex = re.compile (r '(\ d \ d \ d) - (\ d \ d \ d- \ d \ d \ d \ d)') >>> Mo = phoneNumRegex.search (Mia nombro estas 415-555-4242. ') >>> Mo.group (1) '415' >>> Mo.group (2) '555-4242' >>> Mo.group (0) '415-555-4242' >>> Mo.group () '415-555-4242'
Se vi ŝatus preni ĉiuj grupoj samtempe, uzi la
groups()
metodo-noti la plurala formo por la nomo. >>> Mo.groups () ( '415', '555-4242') >>> Areacode, mainNumber = mo.groups () >>> Print (Areacode) 415 >>> Print (mainNumber) 555-4242
Ekde
mo.groups()
redonas opo de multoblaj valoroj, vi povas uzi la multoblaj-asigno
lertaĵo atribui ĉiu valoro al aparta variablo, kiel en la antaŭa areaCode, mainNumber = mo.groups()
linio.
Krampoj havas specialan signifon en regulesprimoj, sed kion fari se vi bezonas kongrui paréntesis en via teksto? Ekzemple, eble la telefonnumerojn vi provas kongrui havas la prefijo metita en krampoj. En tiu kazo, vi devas eviti la
(
kaj )
karakteroj kun backslash. Eniri la sekva en la interaga konko: >>> PhoneNumRegex = re.compile (r '(\ (\ d \ d \ d \)) (\ d \ d \ d- \ d \ d \ d \ d)') >>> Mo = phoneNumRegex.search (Mia telefonnumero estas (415) 555-4242. ') >>> Mo.group (1) (415) ' >>> Mo.group (2) '555-4242'
La
\(
kaj \)
eskapi karakteroj en la kruda ŝnuro pasita al re.compile()
kongruas reala parentezo karakteroj. Egalante Multoblaj Grupoj kun la Pipo
La
|
karaktero estas nomita pipo. Vi povas uzi ĝin ie ajn vi volas kongruas unu el multaj esprimoj. Ekzemple, la regula esprimo r'Batman|Tina Fey'
kongruas ĉu 'Batman'
aŭ 'Tina Fey'
.
Kiam ambaŭ Batman kaj Tina Fey okazi en la traserĉis kordo, la unua apero de trafitaj teksto estos reen kiel
Match
objekto. Eniri la sekva en la interaga konko: >>> HeroRegex = re.compile (r'Batman | Tina Fey ') >>> Mo1 = heroRegex.search ( 'Batman kaj Tina Fey.') >>> Mo1.group () 'Batman' >>> Mo2 = heroRegex.search ( 'Tina Fey kaj Batman.') >>> Mo2.group () 'Tina Fey'
noto
Vi povas trovi ĉiuj egalante spritaĵojn per
findall()
metodo kiu estas diskutita en La findall () Metodo .
Vi povas ankaŭ uzi la pipon por kongrui unu el pluraj ŝablonoj kiel parto de via regex. Ekzemple, diru vi volis konvenas iun el la kordoj
'Batman'
, 'Batmobile'
, 'Batcopter'
kaj 'Batbat'
. Ĉar ĉiuj tiuj kordoj komencas kun Bat
, estus bela se vi povus specifi ke prefikso nur unufoje. Tio povas esti farita per krampoj. Eniri la sekva en la interaga konko: >>> BatRegex = re.compile (r'Bat (viro | mobile | Copter | vesperto) ') >>> Mo = batRegex.search ( 'Batmobile perdis rado') >>> Mo.group () 'Batmobile' >>> Mo.group (1) 'Movebla'
La metodo alvoko
mo.group()
redonas la plenan kongruis teksto 'Batmobile'
, dum mo.group(1)
redonas ĝuste la parto de la kongruis teksto ene la unuaj krampoj grupo, 'mobile'
. Uzante la pipo karaktero kaj kolektante krampoj, vi povas specifi plurajn alternativajn ŝablonoj vi ŝatus vian regex egali.
Se vi bezonas kongruas reala pipo karaktero, eskapi ĝin per backslash, kiel
\|
. Laŭvola Matching kun la Demando Mark
Kelkfoje ekzistas skemo ke vi volas kongruas nur laŭvole. Te la regex devus trovi alumeton ĉu tiu peco de teksto tie. La
?
Karaktero flagoj la grupo kiu antaŭas ŝin kiel laŭvola parto de la ŝablono. Ekzemple, tajpu la sekvajn en la interaga konko: >>> BatRegex = re.compile (r'Bat (wo)? Iu ') >>> Mo1 = batRegex.search ( 'La Aventuroj de Batman) >>> Mo1.group () 'Batman' >>> Mo2 = batRegex.search ( 'La Aventuroj de Batwoman') >>> Mo2.group () 'Batwoman'
La
(wo)?
Parto de la regula esprimo signifas ke la mastro wo
estas laŭvola grupo. La regex kongruas teksto kiu havas nulon kazoj aŭ unu okazo de wo en ĝi. Jen kial la regex matĉojn ambaŭ 'Batwoman'
kaj 'Batman'
.
Uzante la fruaj telefonnumero Ekzemple, vi povas fari la regex atendos telefonnumerojn kiuj faras aŭ ne havas prefijo. Eniri la sekva en la interaga konko:
>>> PhoneRegex = re.compile (r '(\ d \ d \ d -)? \ D \ d \ d- \ d \ d \ d \ d') >>> Mo1 = phoneRegex.search (Mia nombro estas 415-555-4242) >>> Mo1.group () '415-555-4242' >>> Mo2 = phoneRegex.search (Mia nombro estas 555-4242) >>> Mo2.group () '555-4242'
Vi povas pensi pri la
?
Kiel diri: "Match nul aŭ unu el la grupo antaŭan ĉi demandosigno."
Se vi bezonas kongruas reala demandosigno karaktero, eskapi ĝin per
\?
. Egalante Nulo aŭ Pli kun la Stelo
La
*
(nomita la stelo aŭ asterisko) signifas "partio nulo aŭ pli" -la grupo kiu antaŭas la stelo povas okazi ajnan nombron da fojoj en la teksto. Ĝi povas esti tute forestanta aŭ ripetita denove kaj denove denove. Ni rigardu la Batman ekzemplo denove. >>> BatRegex = re.compile (r'Bat (wo) * viro ') >>> Mo1 = batRegex.search ( 'La Aventuroj de Batman) >>> Mo1.group () 'Batman' >>> Mo2 = batRegex.search ( 'La Aventuroj de Batwoman') >>> Mo2.group () 'Batwoman' >>> Mo3 = batRegex.search ( 'La Aventuroj de Batwowowowoman') >>> Mo3.group () 'Batwowowowoman'
Por
'Batman'
, la (wo)*
parto de la regex egalas nulon petskribojn de wo
en la ĉeno; por 'Batwoman'
, la (wo)*
egalas unu okazo de wo
; kaj por 'Batwowowowoman'
, (wo)*
egalas kvar kazojn de wo
.
Se vi bezonas kongruas reala stelo karaktero, prefikson la stelo en la regula esprimo kun backslash,
\*
. Egalante Unu aŭ pli kun la Alpago
Dum
*
signifas "egalas nulo aŭ pli," la +
(aŭ pli)
signifas "kongrui unu aŭ pli." Male al la stelo, kiu ne postulas lia
grupo por aperi en la egalita ŝnuro, la grupo antaŭaj alpago devas aperi
almenaŭ unufoje. Ne estas laŭvola. Eniri la sekva en la interaga ŝelo, kaj kompari ĝin kun la stelo regexes en la antaŭa sekcio: >>> BatRegex = re.compile (r'Bat (wo) + viro ') >>> Mo1 = batRegex.search ( 'La Aventuroj de Batwoman') >>> Mo1.group () 'Batwoman' >>> Mo2 = batRegex.search ( 'La Aventuroj de Batwowowowoman') >>> Mo2.group () 'Batwowowowoman' >>> Mo3 = batRegex.search ( 'La Aventuroj de Batman) >>> Mo3 == None veraj
La regex
Bat(wo)+man
ne kongruas la ĉeno 'The Adventures of Batman'
ĉar almenaŭ wo
estas postulita de la signo.
Se vi bezonas kongruas reala signo karakteron, prefikson la signo kun backslash eskapi ĝin:
\+
. Egalante Specifaj Ripetoj kun Curly krampoj
Se vi havas grupon kiun vi volas ripeti specifa nombro de fojoj, sekvi la grupon en via regex kun nombro en bukla krampoj. Ekzemple, la regex
(Ha){3}
kongruas la kordo 'HaHaHa'
, sed ĝi ne egalas 'HaHa'
, ĉar la lasta havas nur du ripetoj de la (Ha)
grupo.
Anstataŭ unu nombro, vi povas specifi gamon skribante minimumo, komo, kaj maksimuma intere la krispa krampoj. Ekzemple, la regex
(Ha){3,5}
kongruas 'HaHaHa'
, 'HaHaHaHa'
kaj 'HaHaHaHaHa'
.
Vi povas ankaŭ preterlasu la unua aŭ dua numero en la krispa krampoj forlasi la minimumo aŭ maksimumo nebarita. Ekzemple,
(Ha){3,}
kongruas tri aŭ pli instancojn de la (Ha)
grupo, dum (Ha){,5}
kongruas nulo al kvin kazojn. Krispa krampoj povas helpi fari viajn regulajn esprimojn pli mallonga. Tiuj du regulaj esprimoj kongruas identaj ŝablonoj: (Ha) {3} (Ha) (Ha) (Ha)
Kaj tiuj du regulaj esprimoj ankaŭ kongrui identaj ŝablonoj:
(Ha) {3,5} ((Ha) (Ha) (Ha)) | ((Ha) (Ha) (Ha) (Ha)) | ((Ha) (Ha) (Ha) (Ha) (Ha))
Eniri la sekva en la interaga konko:
>>> HaRegex = re.compile (r '(Ha) {3}') >>> Mo1 = haRegex.search ( 'hahaha) >>> Mo1.group () 'Hahaha' >>> Mo2 = haRegex.search ( 'Ha') >>> Mo2 == None veraj
Tie,
(Ha){3}
egalas 'HaHaHa'
sed ne 'Ha'
. Ĉar ĝi ne konvenas 'Ha'
, search()
redonas None
. Avidaj kaj Nongreedy Matching
Ekde
(Ha){3,5}
povas egali tri, kvar, aŭ kvin kazojn de Ha
en la kordo 'HaHaHaHaHa'
, vi povas scivoli kial la Match
objekto voko al group()
en la antaŭa krispa krampo ekzemple revenas 'HaHaHaHaHa'
anstataŭ malplilongigita ebloj. Post ĉiu, 'HaHaHa'
kaj 'HaHaHaHa'
estas ankaŭ valida matĉojn de la regula esprimo (Ha){3,5}
.
Python regulesprimoj estas avidaj defaŭlte, kio signifas ke en ambiguaj situacioj ili egalas la plej longa ŝnuro eble. La ne-avidaj versio de la krispa krampoj, kio egalas la plej mallonga ĉeno eblas, havas la fermante krispa krampo sekvita de demandosigno.
Eniri la sekva en la interaga ŝelo, kaj rimarki la diferencon inter la
avidaj kaj nongreedy formoj de la krispa krampoj serĉanta la sama ĉeno:
>>> GreedyHaRegex = re.compile (r '(Ha) {3,5}') >>> Mo1 = greedyHaRegex.search ( 'HaHaHaHaHa') >>> Mo1.group () 'HaHaHaHaHa' >>> NongreedyHaRegex = re.compile (r '(Ha) {3,5}?') >>> Mo2 = nongreedyHaRegex.search ( 'HaHaHaHaHa') >>> Mo2.group () 'Hahaha'
Notu ke la demandosigno povas havi du signifojn en regulesprimoj: deklari nongreedy matĉo aŭ denuncas laŭvola grupo. Tiuj signifoj estas tute senrilataj.
La findall () Metodo
Krom la
search()
metodon, Regex
objektoj ankaŭ havas findall()
metodo. Dum search()
revenos Match
objekto de la unua kongruis teksto en la traserĉis kordo, la findall()
metodo revenos la kordoj de ĉiu matĉo en la traserĉis ŝnuro. Vidi kiel search()
redonas Match
objekto nur en la unua petskribo de trafitaj tekston, tajpu la sekvajn en la interaga konko: >>> PhoneNumRegex = re.compile (r '\ d \ d \ d- \ d \ d \ d- \ d \ d \ d \ d') >>> Mo = phoneNumRegex.search ( 'Ĉelo: 415-555-9999 Laboro: 212-555-0000) >>> Mo.group () '415-555-9999'
Aliflanke,
findall()
ne resendas Match
objekto sed listo de strings- tiel longe kiel ekzistas neniu grupoj en la regula esprimo. Ĉiu ŝnuro en la listo estas peco de la traserĉis tekston kiu kongruis regula esprimo. Eniri la sekva en la interaga konko: >>> PhoneNumRegex = re.compile (r '\ d \ d \ d- \ d \ d \ d- \ d \ d \ d \ d') # havas neniun grupoj >>> PhoneNumRegex.findall ( 'Ĉelo: 415-555-9999 Laboro: 212-555-0000) [ '415-555-9999', '212-555-0000']
Se ekzistas grupoj en la regula esprimo, tiam
findall()
revenos listo de opoj. Ĉiu opo reprezentas trovis matĉon, kaj liaj artikoloj estas la egalita kordoj por ĉiu grupo en la regex. Vidi findall()
en ago, eniri la sekva en la interaga ŝelo (rimarki ke la regula esprimo esti kompilita nun havas grupojn en krampoj): >>> PhoneNumRegex = re.compile (r '(\ d \ d \ d) - (\ d \ d \ d) - (\ d \ d \ d \ d)') # havas grupojn >>> PhoneNumRegex.findall ( 'Ĉelo: 415-555-9999 Laboro: 212-555-0000) [( '415', '555', '9999'), ( '212', '555', '0000')]
Resumi kion la
findall()
metodo revenas, memoru la sekvaj: - Kiam vokis sur regex sen grupoj, kiel ekzemple
\d\d\d-\d\d\d-\d\d\d\d
, la metodofindall()
resendas liston de ŝnuro matĉoj, kiel['415-555-9999', '212-555-0000']
. - Kiam vokis sur regex kiu havas grupojn, kiel
(\d\d\d)-(\d\d\d)-(\d\ d\d\d)
, la metodofindall()
resendas liston de opoj de kordoj (unu cxeno por ĉiu grupo), kiel ekzemple[('415', '555', '9999'), ('212', '555', '0000')]
.
karaktero klasoj
En la pli frua telefonnumero regex Ekzemple, vi lernis ke
\d
povus signifi ajnan nombra cifero. Tio estas, \d
estas stenografio por la regula esprimo (0|1|2|3|4|5|6|7|8|9)
. Ekzistas multaj tiaj stenografio karaktero klasoj, kiel montrite en Tabelo 7-1 .
Tabelo 7-1. Stenografio Kodoj por Komuna Karaktero klasoj
Stenografio karaktero klaso
|
reprezentas
|
---|---|
\d |
Iu nombra cifero de 0 ĝis 9.
|
\D |
Ajna karaktero kiu ne estas nombra cifero de 0 ĝis 9.
|
\w |
Iu letero, nombra cifero, aŭ la substreko karakteron. (Pensu pri tio kiel egalante "vorto" karakteroj.)
|
\W |
Ajna karaktero kiu ne leteron, nombra cifero, aŭ la substreko karakteron.
|
\s |
Ajna spaco, langeto, aŭ lino karaktero. (Pensu pri tio kiel egalante "spaco" karakteroj.)
|
\S |
Ajna karaktero kiu ne estas spaco, langeto, aŭ lino.
|
Karaktero klasoj estas bela por mallongigi regulesprimoj. La karaktero klaso
[0-5]
kongruas nur la nombrojn 0
ĝis 5
; tio estas multe pli mallonga ol tajpi (0|1|2|3|4|5)
.
Ekzemple, tajpu la sekvajn en la interaga konko:
>>> XmasRegex = re.compile (r '\ d + \ s \ w +') >>> XmasRegex.findall ('12 tamburistoj, 11 flutistoj 10 nobeloj 9 sinjorinoj, 8 servistinoj, 7 cignoj, 6 anseroj, 5 ringoj, 4 birdoj, 3 kokinoj, 2 kolomboj 1 perdriko) ['12 Tamburistoj ', '11 flutistoj', '10 sinjoroj ',' 9 sinjorinoj ',' 8 servistinoj ',' 7 cignoj ',' 6 anseroj ',' 5 ringoj ',' 4 birdoj ',' 3 kokinoj ',' 2 kolombaj, '1 perdriko']
La regula esprimo
\d+\s\w+
kongruas teksto kiu havas unu aŭ pli nombraj ciferoj ( \d+
), sekvitaj de spaceto karaktero ( \s
), sekvita de unu aŭ pli leteron / cifero / substreki karakteroj ( \w+
). La findall()
metodo revenas tutan egalante kordoj de la regex padrono en listo. Farante Your Own Karaktero klasoj
Estas tempoj kiam vi volas kongruas aro de karakteroj sed la stenografio karaktero klasoj (
\d
, \w
, \s
, kaj tiel plu) estas tro larĝaj. Vi povas difini vian propran karakteron klaso uzante rektaj krampoj. Ekzemple, la karaktero klaso [aeiouAEIOU]
kongruas ajna vokalo, ambaŭ minuskla kaj majuskla. Eniri la sekva en la interaga konko: >>> VowelRegex = re.compile (r '[aeiouAEIOU]') >>> VowelRegex.findall ( 'Robocop manĝas bebo manĝaĵo. BABY FOOD.') [ 'O', 'o', 'o', 'e', 'a', 'a', 'o', 'o', 'A', 'ho', 'ho']
Vi povas ankaŭ inkludi rangoj de leteroj aŭ nombroj uzante streketo. Ekzemple, la karaktero klaso
[a-zA-Z0-9]
kongruas ĉiuj minuskla literoj, majusklajn literojn kaj numerojn.
Rimarku ke ene la rektaj krampoj, la normala regula esprimo simboloj ne interpretita kiel tia. Tio signifas ke vi ne bezonas eskapi la
.
, *
, ?
, Aŭ ()
karakteroj kun antaŭaj backslash. Ekzemple, la karaktero klaso [0-5.]
Kongruas ciferoj 0
ĝis 5
kaj periodo. Vi ne bezonas skribi ĝin kiel [0-5\.]
.
Metante ĉapelo karaktero (
^
) ĝuste post la karaktero klaso malfermo krampo, vi povas fari negativan karakteron klaso. Negativa karaktero klaso kongruas ĉiuj karakteroj kiuj ne estas en la karaktero klaso. Ekzemple, tajpu la sekvajn en la interaga konko: >>> ConsonantRegex = re.compile (r '[^ aeiouAEIOU]') >>> ConsonantRegex.findall ( 'Robocop manĝas bebo manĝaĵo. BABY FOOD.') [ 'R', 'b', 'c', 'p', '', 't', 's', '', 'b', 'b', 'y', '', 'f', 'd', '.', ' ',' B ',' B ',' Y ',' ',' F ',' D ','. ']
Nun, anstataŭ egalante ĉiu vokalo, ni egalante ĉiu karaktero kiu ne estas vokalo.
La tekstkursoran kaj Dolaro Signo Karakteroj
Vi povas ankaŭ uzi la ĉapelo simbolo (
^
) ĉe la komenco de regex indiki ke matĉo devas okazi komence de la traserĉis tekston. Simile, vi povas meti dolaro signo ( $
) ĉe la fino de la regex indiki la kordo devas fini kun ĉi regex ŝablono. Kaj vi povas uzi la ^
kaj $
kune indiki ke la tuta ĉeno devas parigi la regex-te ĝi ne sufiĉas por turniro por esti farita sur iu subaro de la kordo.
Ekzemple, la
r'^Hello'
regula esprimo ŝnuro matĉojn kordoj kiuj komencas kun 'Hello'
. Eniri la sekva en la interaga konko: >>> BeginsWithHello = re.compile (r '^ Saluton') >>> BeginsWithHello.search ( 'Saluton mondo!') <_sre.SRE_Match Objekto; interspaco = (0, 5), turniro = 'Saluton'> >>> BeginsWithHello.search ( 'Li diris saluton.') == None veraj
La
r'\d$'
regula esprimo ŝnuro matĉojn kordoj kiuj finas kun nombra karaktero de 0 al 9. Entajpu la sekva en la interaga konko: >>> EndsWithNumber = re.compile (r '\ d $') >>> EndsWithNumber.search ( 'Via nombro estas 42') <_sre.SRE_Match Objekto; interspaco = (16, 17), turniro = '2'> >>> EndsWithNumber.search ( 'Via nombro estas kvardek du.') == None veraj
La
r'^\d+$'
regula esprimo ŝnuro matĉojn kordojn kiujn ambaŭ komencas kaj finiĝas per unu aŭ pli nombraj karakteroj. Eniri la sekva en la interaga konko: >>> WholeStringIsNum = re.compile (r '^ \ d + $') >>> WholeStringIsNum.search ( '1234567890') <_sre.SRE_Match Objekto; interspaco = (0, 10), turniro = '1234567890'> >>> WholeStringIsNum.search ( '12345xyz67890') == None veraj >>> WholeStringIsNum.search ('12 34567890 ') == None veraj
La lastaj du
search()
nomas en la antaŭa interaga ŝelon ekzemplo pruvas kiel la tuta ĉeno devas parigi la regex se ^
kaj $
estas uzataj.
Mi ĉiam konfuzas la signifojn de tiuj du simboloj, do mi uzas la
mnemonika "Karotoj kosto dolaroj" por memorigi min ke la ĉapelo venas
unua kaj la dolaro signo venas lasta.
La Ĵokero
La
.
(Aŭ punkto) karaktero en regula esprimo nomiĝas ĵokero kaj kongruas ajna karaktero krom lino. Ekzemple, tajpu la sekvajn en la interaga konko: >>> AtRegex = re.compile (r'.at ') >>> AtRegex.findall ( 'La kato en la ĉapelo sidis sur la plata mato.') [ 'Kato', 'apelo', 'sidis', 'lat', 'mato']
Memoru ke la skalara karaktero kongruas nur unu signo, Kiu estas kial la matĉo por la teksto
flat
en la antaŭa ekzemplo egalita nur lat
. Parigi reala streketo eskapi la skalara kun backslash: \.
. Egalante Ĉiu kun Dot-Star
Kelkfoje vi volas kongruas ĉiu kaj ĉiu. Ekzemple, diru ke vi volas parigi la kordo
'First Name:'
, sekvita de iu kaj ĉiuj teksto, sekvata de 'Last Name:'
, kaj tiam sekvita per io pli. Vi povas uzi la skalara-stelo ( .*
) Stari en por ke "io." Memoru ke la skalara karaktero signifas "unuopa
signo krom la linion," kaj la steloj karaktero signifas "nul aŭ pli de
la antaŭa signo."
Eniri la sekva en la interaga konko:
>>> NameRegex = re.compile (r'First Nomo (. *) Lasta Nomo (. *) ') >>> Mo = nameRegex.search ( 'Unua Nomo Al Lasta Nomo Sweigart') >>> Mo.group (1) 'Al' >>> Mo.group (2) 'Sweigart'
La skalara-stelo uzas avidaj reĝimo: ĝi ĉiam provu parigi tiel teksto kiel ebla. Parigi ĉiaj kaj ĉiuj teksto en nongreedy modo, uzu la streketo stelo kaj demandosigno (
.*?
). Kiel kun krispa krampoj, la demandosigno diras Python parigi en nongreedy vojo.
Eniri la sekva en la interaga ŝelo vidi la diferencon inter la avidaj kaj nongreedy versioj:
>>> NongreedyRegex = re.compile (r '<. *?>') >>> Mo = nongreedyRegex.search ( '<Servi viro> por vespermanĝo.>') >>> Mo.group () '<Servi viro>' >>> GreedyRegex = re.compile (r '<. *>') >>> Mo = greedyRegex.search ( '<Servi viro> por vespermanĝo.>') >>> Mo.group () '<Servi viro> por vespermanĝo.>'
Ambaŭ regexes malglate tradukas al "Trafu malfermo angulo krampo,
sekvita de io, sekvita per fermo angulo krampo." Sed la kordo
'<To serve man> for dinner.>'
Havas du eblajn matĉojn por la fermo angulo krampo. En la nongreedy versio de la regex, Pitono egalas la plej mallonga ebla ŝnuro: '<To serve man>'
. En la avidaj versio, Pitono egalas la plej longa ebla ŝnuro: '<To serve man> for dinner.>'
. Egalante linifinojn kun la Dot Karaktero
La skalara-stelo egalas ĉiun krom novan linion. Pasante
re.DOTALL
kiel la dua argumento al re.compile()
, vi povas fari la punkton karaktero matĉo ĉiuj karakteroj, inkluzive de la nova linio karaktero.
Eniri la sekva en la interaga konko:
>>> NoNewlineRegex = re.compile ( '. *') >>> NoNewlineRegex.search ( 'Servu la publikan konfidon. \ NProtect senkulpuloj. \ nUphold la leĝo. "). grupo () 'Servu la publikan konfidon. >>> NewlineRegex = re.compile ( '. *', Re.DOTALL) >>> NewlineRegex.search ( 'Servu la publikan konfidon. \ NProtect senkulpuloj. \ nUphold la leĝo. "). grupo () 'Servu la publikan konfidon. \ NProtect senkulpuloj. \ NUphold la leĝo. "
La regex
noNewlineRegex
, kiu ne havis re.DOTALL
pasis al la re.compile()
alvoko kiu kreis ĝin, kongruas ĉio nur ĝis la unua linion karaktero, dum newlineRegex
, kiuj ja havis re.DOTALL
pasis al re.compile()
, egalas ĉiun. Jen kial la newlineRegex.search()
alvoko egalas la plena kordo, Inkluzivanta lian linion karakteroj. Revizio de Regex Simboloj
Ĉi tiu ĉapitro kovras multon de skribmaniero, do jen rapida revizio de kion vi lernis:
- La
?
Egalas nulo aŭ unu el la antaŭaj grupo. - La
*
egalas nulo aŭ pli el la antaŭaj grupo. - La
+
egalas unu aŭ pli el la antaŭaj grupo. - La
{n}
alumetoj ĝuste n de la antaŭa grupo. - La
{n,}
alumetoj n aŭ pli el la antaŭaj grupo. - La
{,m}
alumetoj 0 al m de la antaŭa grupo. - La
{n,m}
alumetoj almenaŭ n kaj maksimume m de la antaŭa grupo. {n,m}?
aŭ*?
aŭ+?
elfaras nongreedy matĉo de la antaŭa grupo.^spam
signifas la ŝnuro devas komenciĝi per spamado .spam$
signifas la kordo devas finiĝi per spamado .- La
.
alumetoj ajna karaktero, krom linion karakteroj. \d
,\w
Kaj\s
kongruas cifero, vorto, aŭ spaceto, respektive.\D
,\W
Kaj\S
kongruas io krom ciferoj, vorto, aŭ spaceto, respektive.[abc]
egalas ajnan karakteron inter la krampoj (kiel oni , b , aŭ c ).[^abc]
egalas ajnan karakteron kiu estas ne inter la krampoj.
Kazo-sensenta Matching
Normale regulesprimoj kongruas teksto kun la ĝusta carcasa vi specifas. Ekzemple, jena regexes kongruas tute malsamaj kordoj:
>>> Regex1 = re.compile ( 'Robocop') >>> regex2 = re.compile ( 'Robocop') >>> regex3 = re.compile ( 'Robocop') >>> regex4 = re.compile ( 'Robocop ')
Sed foje vi zorgas nur pri egalante la leteroj sen zorgi ĉu ili estas majuskla aŭ minuskla. Fari vian regex kazo-sensenta, vi povas pasi
re.IGNORECASE
aŭ re.I
kiel dua argumento al re.compile()
. Eniri la sekva en la interaga konko: >>> RoboCop = re.compile (r'robocop ', re.I) >>> robocop.search (' Robocop estas parto viro, parto maŝino, ĉiu policano. '). Grupo () 'Robocop' >>> Robocop.search ( 'Robocop protektas la senkulpajn.'). Grupo () 'Robocop' >>> Robocop.search ( 'Al, kial faras via programado libro diskuto pri RoboCop tiom?). Grupo () ' RoboCop '
Anstataŭiganta Strings kun la sub () Metodo
Regulaj esprimoj povas ne nur trovi teksto ŝablonoj sed povas ankaŭ anstataŭigi novan tekston en lokon de tiuj ŝablonoj. La
sub()
metodo por Regex
objektoj estas pasita du argumentojn. La unua argumento estas ĉeno anstataŭi ajnan matĉoj. La dua estas la ŝnuro por la regula esprimo. La sub()
metodo redonas ĉenon kun la anstataŭigoj aplikita.
Ekzemple, tajpu la sekvajn en la interaga konko:
>>> NamesRegex = re.compile (r'Agent \ w + ') >>> namesRegex.sub (' cenzurita ',' Agento Alicia donis la sekretaj dokumentoj al Agent Bob. ') ' Cenzurita donis la sekretaj dokumentoj al cenzurita.
Kelkfoje vi eble bezonas uzi la kongruis teksto mem kiel parto de la anstataŭo. En la unua argumento al
sub()
, Vi povas tajpi \1
, \2
, \3
, kaj tiel plu, por signifi "Enmetu la tekston de grupo 1
, 2
, 3
, kaj tiel plu, en la anstataŭo."
Ekzemple, diru ke vi volas cenzuri la nomoj de la sekretaj agentoj montrante nur la unuaj leteroj de iliaj nomoj. Por fari tion, vi povus uzi la regex
Agent (\w)\w*
migru r'\1****'
kiel la unua argumento al sub()
. La \1
en tiu ĉeno estos anstataŭigita per nenial teksto estis egalita fare grupo 1
Ke estas, la (\w)
grupo de la regula esprimo.>>> AgentNamesRegex = re.compile (r'Agent (\ w) \ w * ') >>> agentNamesRegex.sub (r' \ 1 **** ',' Agento Alico diris Agento Carol ke Agento Eva sciis Agent Bob estis duobla agento. ') A **** diris C **** ke E **** sciis B **** estis duobla agento.
Administranta Kompleksa Regexes
Regulaj esprimoj estas bone se la teksto padrono vi devas kongrui estas simpla. Sed egalante komplika teksto ŝablonoj povus postuli longan, convoluted regulesprimoj. Vi povas mildigi ĉi de diranta la
re.compile()
funkcio ignori spaceto kaj komentoj ene la regula esprimo ŝnuro. Tiu "abundajn mode" povas esti ebligita per pasante la variablo re.VERBOSE
kiel la dua argumento al re.compile()
.
Nun anstataŭ malmola-al-legi regulan esprimon tiel:
phoneRegex = re.compile (r '((\ d {3} | \ (\ d {3} \))? (\ s | - | \.)? \ d {3} (\ s | - | \. ) \ d {4} (\ S * (ext | x | ext.) \ S \ d {2,5})?) ')
Vi povas sendi la regula esprimo super multoblaj linioj kun komentoj kiel ĉi:
phoneRegex = re.compile (r '' '( (\ D {3} | \ (\ d {3} \))? # Prefijo (\ S | - | \.)? # apartigilon \ D {3} # unuaj 3 ciferoj (\ S | - | \.) # Apartigilon \ D {4} # lasta 4 ciferoj (\ S * (ext | x | ext.) \ S \ d {2,5})? # etendo ) '' ', Re.VERBOSE)
Notu kiel la antaŭa ekzemplo uzas la triobla-citaĵo sintakso (
'''
) por krei multiline ŝnuro tiel ke vi povas sendi la regula esprimo difino super multaj linioj, farante ĝin multe pli legebla.
La komento reguloj ene la regula esprimo ŝnuro estas la sama kiel regula Python kodo la
#
simbolo kaj ĉio post ĝi al la fino de la linio estas ignoritaj. Ankaŭ,
la ekstra spacoj ene la multiline ŝnuro por la regula esprimo ne estas
konsideritaj parto de la teksto padrono esti egalita. Tiu permesas organizi la regula esprimo do estas pli facile legi.Kombinante re.IGNORECASE, re.DOTALL kaj re.VERBOSE
Kio se vi volas uzi
re.VERBOSE
por skribi komentojn en via regula esprimo sed ankaŭ volas uzi re.IGNORECASE
ignori capitalización? Bedaŭrinde, la re.compile()
funkcio prenas nur sola valoro kiel ĝia dua argumento. Vi povas preni ĉirkaŭ ĉi limigo kombinante la re.IGNORECASE
, re.DOTALL
kaj re.VERBOSE
variabloj uzante la pipo karaktero ( |
), kiu en tiu kunteksto estas konata kiel la bitlarĝa aŭ operatoro.
Do se vi volas regula esprimo tio kazo-sensenta kaj inkluzivas linifinojn parigi la skalara rolanto vi formus vian
re.compile()
alvokon tiamaniere:>>> SomeRegexValue = re.compile ( 'umo', re.IGNORECASE | re.DOTALL)
Ĉiuj tri ebloj por la dua argumento aspektos tiel ĉi:
>>> SomeRegexValue = re.compile ( 'umo', re.IGNORECASE | re.DOTALL | re.VERBOSE)
Tiu sintakso estas iom malmoderna kaj originas el fruaj versioj de Pitono. La detaloj de la bitlarĝa operatoroj estas preter la kadro de tiu libro, sed kontrolu la rimedoj je http://nostarch.com/automatestuff/ por pli informo. Vi povas ankaŭ pasas aliaj ebloj por la dua argumento; ili estas nekomuna, sed vi povas legi pli pri ili en la rimedoj ankaŭ.
Projekto: Telefonnumero kaj Poŝtadreso Eltirilo
Diru vi havas la enuiga tasko de trovi ĉiun telefonnumero kaj retadreso en longa retpaĝo aŭ dokumento. Se vi permane rulumi tra la paĝo, vi povus fini serĉis delonge. Sed se vi havis programon kiu povus serĉi la tekston en via tondujo por telefonnumerojn kaj retadresojn, vi povus simple premu CTRL -A elekti la tutan tekston, gazetaro CTRL -C kopii ĝin al la tondujo kaj poste ekzekuti vian programon . Ĝi povus anstataŭi la teksto sur la tondujo per nur la telefonnumerojn kaj retadresojn trovas.
Kiam ajn vi pritrakti nova projekto, ĝi povas esti tentanta plonĝi rekte en skribo kodo. Sed pli ofte ol ne, ĝi estas bona por preni retropaŝon kaj konsideri la grandan bildon. Mi rekomendas unua strekitaj altnivelan planon por kio via programo bezonas fari. Ne pensu pri la reala kodo tamen-vi povas zorgi pri tio poste. Nun, algluita al grandaj trajtoj.
Ekzemple, via telefono kaj retadreso extractor bezonos fari la sekvajn:
- Akiri la teksto for la tondujo.
- Trovu ĉiujn telefonnumerojn kaj retadresojn en la teksto.
- Algluu ilin sur la tondujo.
Nun vi povas komenci pensi pri kiel ĉi povus labori en kodo. La kodo devas fari la sekvajn:
- Uzi la
pyperclip
modulon kopii kaj alglui ŝnurojn. - Krei du regexes, unu por egalante telefonnumerojn kaj la alia por egalante retadresoj.
- Trovu ĉiujn matĉojn, ne nur la unuan matĉon, tiel regexes.
- Nete formati la kongruis kordoj en sola ĉeno algluota.
- Montri ian mesaĝon se neniu matĉoj estis trovitaj en la teksto.
Tiu listo estas kiel irletero por la projekto. Kiel vi skribas la kodon, vi povas enfokusigi ĉiun de ĉi tiuj paŝoj aparte. Ĉiu paŝo estas sufiĉe regebla kaj esprimita en terminoj de aĵoj vi jam scias kiel fari en Python.
Paŝo 1: Krei Regex por Telefonaj Nombroj
Unue, vi devas krei regulan esprimon por serĉi telefonnumerojn. Krei novan dosieron, tajpu la sekvan, kaj konservi ĝin kiel phoneAndEmail.py :
#! python3 # PhoneAndEmail.py - Trovas telefonnumerojn kaj retadresojn de la tondujo. importado pyperclip, re phoneRegex = re.compile (r '' '( (\ D {3} | \ (\ d {3} \))? # Prefijo (\ S | - | \.)? # apartigilon (\ D {3}) # 3 unuaj ciferoj (\ S | - | \.) # Apartigilon (\ D {4}) # lastaj 4 ciferoj (\ S * (ext | x | ext.) \ S * (\ d {2,5}))? # etendo ) '' ', Re.VERBOSE) # TODO: Krei retpoŝto regex. # TODO: Trovu matĉojn en tondujo tekston. # TODO: Kopiu rezultojn al la tondujo.
La
TODO
komentoj estas nur skeleto por la programo. Ili estos anstataŭigita kiel vi skribas la reala kodo.
La telefonnumero komencas kun laŭvola prefijo, tial la prefijo grupo sekvis kun demandosigno. Ekde la prefijo povas esti nur tri ciferoj (te
\d{3}
) aŭ tri ciferoj ene krampoj (te \(\d{3}\)
), vi devus havi pipo aliĝado tiuj partoj. Vi povas aldoni la regex komenton # Area code
al tiu parto de la multiline ŝnuro helpi vin memori kion (\d{3}|\(\d{3}\))?
oni supozis egali.
La telefonnumero separador karakteron povas esti interspaco (
\s
), streketo ( -
), aŭ periodo ( .
), do tiuj partoj devas ankaŭ esti aligita fare pipoj. La venontaj partoj de la regula esprimo estas simpla: tri ciferoj, sekvita per alia disigilo, sekvita de kvar ciferoj. La lasta parto estas laŭvola etendaĵo konsistas el iu nombro da spacoj sekvas ext
, x
aŭ ext.
, sekvita per du al kvin ciferoj.Paŝo 2: Krei Regex por Retpoŝto Adresoj
Vi ankaŭ bezonas regulan esprimon kiu povas egali retadresoj. Fari vian programon aspektas kiel la sekvaj:
#! python3 # PhoneAndEmail.py - Trovas telefonnumerojn kaj retadresojn de la tondujo. importado pyperclip, re phoneRegex = re.compile (r '' '( --snip-- # Krei retpoŝto regex. EmailRegex = re.compile (r '' '( ❶ [a-za-Z0-9 ._% + -] + # salutnomo ❷ @ # @ simbolo ❸ [a-za-Z0-9.- ] + # domajnnomo (\. [a-za-Z] {2,4}) # punkto-io ) '' ', re.VERBOSE) # TODO: Trovu matĉojn en tondujo tekston. # TODO: Kopiu rezultojn al la tondujo.
La
salutnomo parto de la retadreso ❶ estas unu aŭ plurajn signojn kiu
povas esti iu ajn el la sekvaj: minuskla kaj majuskla literoj, ciferoj,
punkto, substreko, procentsigno, alpago signo, aŭ streketo. Vi povas meti ĉiujn tiujn en karaktero klaso:
[a-zA-Z0-9._%+-]
.
La domajno kaj uzantnomo estas apartigitaj per @ simbolo ❷. La domajnnomo ❸ havas iomete malpli permisiva karaktero klaso kun nur literoj, ciferoj, periodoj, kaj streketoj:
[a-zA-Z0-9.-]
. Kaj lastaj estos la "punkto-com" parto (teknike konata kiel la supro-nivelo regado ), kiu povas vere esti punkto-io. Tio estas inter du kaj kvar karakteroj.
La formato por retadresoj havas multajn strangajn regulojn. Tiu
regula esprimo ne kongruas ĉiu ebla valida retpoŝta adreso, sed ĝi
malebligos kongruas preskaŭ ajna tipa retadreson vi renkontas.
Paŝo 3: Trovu Ĉiuj Matĉoj en la poŝo Teksto
Nun ke vi specifis la regulesprimoj por telefonnumerojn kaj retadresojn, vi povas lasi Python
re
modulo faras la malfacilan laboron de trovi ĉiujn matĉojn sur la tondujo. La pyperclip.paste()
funkcio ricevos kordo valoro de la teksto sur la tondujo, kaj la findall()
regex metodo revenos listo de opoj.
Fari vian programon aspektas kiel la sekvaj:
#! python3 # PhoneAndEmail.py - Trovas telefonnumerojn kaj retadresojn de la tondujo. importado pyperclip, re phoneRegex = re.compile (r '' '( --snip-- # Trovu matĉojn en tondujo tekston. Text = str (pyperclip.paste ()) ❶ alumetoj = [] ❷ por grupoj en phoneRegex.findall (teksto): phoneNum = '-'. Aliĝi ([grupojn [1], grupoj [3 ], grupoj [5]]) , se grupoj [8]! = '': phoneNum + = 'x' + grupoj [8] matches.append (phoneNum) ❸ por grupoj en emailRegex.findall (teksto): matches.append ( grupoj [0]) # TODO: Kopiu rezultojn al la tondujo.
Ekzistas unu opo por ĉiu matĉo, kaj ĉiu opo enhavas kordoj por ĉiu grupo en la regula esprimo. Memoras ke grupo
0
egalas la tuta regula esprimo, tiel la grupo ĉe indekso 0
de la opo estas la unu vi interesiĝas.
Kiel vi povas vidi ĉe ❶, vi stoki la alumetoj en lerta variablo nomata
matches
. Ĝi komenciĝas for kiel malplena listo kaj paro for
cikloj. Por la retadresojn, vi postglui grupo 0
de ĉiu matĉo ❸. Por la kongruis telefonnumerojn, vi ne volas nur postglui grupo 0
. Dum la programo detektas telefonnumerojn en pluraj formatoj, Vi volas la telefonnumero almuntita esti en ununura, norma formato. La phoneNum
variablo enhavas kordo konstruita de grupoj 1
, 3
, 5
, kaj 8
de la kongruis teksto ❷. (Tiuj grupoj estas la prefijo, unuaj tri ciferoj, lastaj kvar ciferoj, kaj sufikso.)Paŝo 4: Join la Turniroj en String por la poŝo
Nun ke vi havas la retadresojn kaj telefonnumerojn kiel listo de kordoj en
matches
, vi volas meti ilin en la tondujo. La pyperclip.copy()
funkcio prenas nur ununura ĉeno valoro, ne listo de kordoj, tiel vi nomas la join()
metodon sur matches
.
Plifaciligi por vidi ke la programo funkcias, ni presi ajnan alumetoj vi trovas al la fina stacio. Kaj se neniu telefonnumerojn aŭ retadresoj estis trovita, la programo devus diri la uzanto ĉi.
Fari vian programon aspektas kiel la sekvaj:
#! python3 # PhoneAndEmail.py - Trovas telefonnumerojn kaj retadresojn de la tondujo. --snip-- por grupoj en emailRegex.findall (teksto): matches.append (grupoj [0]) # Kopiu rezultojn al la tondujo. Se len (egalas)> 0: pyperclip.copy ( '\ n'.join (alumetoj)) print (' Kopiita al interdeponejo: ') print (' \ n'.join (alumetoj)) alie: print ( 'Neniu telefonnumerojn aŭ retadresoj trovita.)
Kurante la programo
Por ekzemplo, malfermu vian retumilon al la Neniu amelo Gazetara kontakto paĝo ĉe http://www.nostarch.com/contactus.htm , premu CTRL -A elekti la tutan tekston en la paĝo, kaj premu CTRL -C kopii ĝin al la tondujo. Kiam vi kuros ĉi programo, la eligo aspektos ion kiel jene:
Kopiitaj al tondujo: 800-420-7240 415-863-9900 415-863-9950 info@nostarch.com media@nostarch.com academic@nostarch.com help@nostarch.com
Ideoj por Similaj Programoj
Identiganta mastroj de teksto (kaj eble anstataŭiganta ilin kun la
sub()
metodo) havas multajn diversajn eblajn aplikojn.- Trovu retejo URLoj kiuj komencas kun http: // aŭ https: // .
- Purigu datoj en malsama dato formatoj (kiel 3/14/2015, 03-14-2015, kaj 2015/3/14) anstataŭigante ilin kun datoj en sola, norma formato.
- Forigi sentema informojn kiel Socia Sekureco aŭ kreditkarto nombroj.
- Trovi komunan tajperarojn kiel multnombraj spacoj inter vortoj, hazarde hazarde ripetis vortojn, aŭ multoblaj Krisigno fine de frazoj. Tiuj estas ĝena !!
resumo
Dum komputilo povas serĉi tekston rapide, ĝi devas esti dirita precize kion serĉi. Regulesprimoj permesas vin specifi la precizan mastroj de karakteroj vi serĉas. Fakte,
iuj tekstoprilaborado kaj kalkultabelo aplikoj havigas
trovi-kaj-anstataŭigi trajtoj kiuj permesas vin serĉi per regulaj
esprimoj.
La
re
modulo kiu venas kun Python permesas kompili Regex
objektoj. Tiuj valoroj havas plurajn metodojn: search()
trovi ununura matĉo, findall()
trovi ĉiujn egalante ekzemplojn kaj sub()
fari trovaĵo-kaj-anstataŭigi anstataŭo de teksto.
Ekzistas iom pli al regula esprimo sintakso kiu estas priskribita en ĉi ĉapitro. Vi povas trovi ekstere pli da en la oficiala Python dokumentado ĉe http://docs.python.org/3/library/re.html . La lernilo retejo http://www.regular-expressions.info/ estas ankaŭ utila rimedo.
Nun ke vi havas kompetentecon manipulado kaj egalante kordoj, estas
tempo por plonĝi en kiel legi de kaj skribi al dosieroj sur via
komputilo malmola disko.
praktiko Demandoj
Q:
|
1. Kio estas la funkcio kiu kreas
Regex objektojn? |
Q:
|
2. Kial kruda kordoj ofte uzata kiam kreante
Regex objektoj? |
Q:
|
3. Kion la
search() metodo revenos? |
Q:
|
4. Kiel vi akiras la reala kordoj kiuj egalas la desegnon de
Match objekto? |
Q:
|
5. En la regex kreita de
r'(\d\d\d)-(\d\d\d-\d\d\d\d)' , kion grupo 0 kovri? Grupo 1 ? Grupo 2 ? |
Q:
|
6. paréntesis kaj periodoj havas specifajn signifojn en regula esprimo sintakso. Kiel volus vin specifi ke vi volas regex parigi reala parentezoj kaj periodo karakteroj?
|
Q:
|
7. La
findall() metodo resendas liston de kordoj aŭ de opoj de kordoj. Kion faras reveni unu aŭ la alia? |
Q:
|
8. Kion la
| karaktero signifas en regulesprimoj? |
Q:
|
9. Kio du aferoj faras la
? karakteron signifas en regulesprimoj? |
Q:
|
10. Kio estas la diferenco inter la
+ kaj * karakteroj en regulesprimoj? |
Q:
|
11. Kio estas la diferenco inter
{3} kaj {3,5} en regulaj esprimoj? |
Q:
|
12. Kion la
\d , \w kaj \s stenografio karaktero klasoj signifi en regulesprimoj? |
Q:
|
13. Kion la
\D , \W kaj \S stenografio karaktero klasoj signifi en regulesprimoj? |
Q:
|
14. Kiel vi faras regulan esprimon kazo-sensenta?
|
Q:
|
15. Kion la
. karaktero kutime kongruas? Kion tio kongruas se re.DOTALL estas pasita kiel la dua argumento al re.compile() ? |
Q:
|
16. Kio estas la diferenco inter tiuj du:
.* kaj.*? |
Q:
|
17. Kio estas la karaktero klaso sintakso parigi ĉiuj nombroj kaj minuskla literoj?
|
Q:
|
18. Se
numRegex = re.compile(r'\d+') kion faros numRegex.sub('X', '12 drummers, 11 pipers, five rings, 3 hens') reveni? |
Q:
|
19. Kion pasi
re.VERBOSE kiel la dua argumento al re.compile() vi permesas fari? |
Q:
|
20. Kiel vi skribos regex kiu kongruas nombro kun komoj por ĉiu tri ciferoj? Ĝi devas parigi la sekvaj:
sed ne la jenaj:
|
Q:
|
21. Kiel vi skribos regex kiu kongruas kun la plena nomo de iu kies familinomo estas Nakamoto? Vi povas supozi, ke la unua nomo kiu venas antaŭ ĝi estos ĉiam unu vorto, kiu komenciĝas per majusklo. La regex devas parigi la sekvaj:
sed ne la jenaj:
|
Q:
|
22. Kiel vi skribos regex kiu kongruas frazo kie la unua vorto estas aŭ Alico , Bob , aŭ Carol ; la dua vorto estas aŭ manĝas , dorlotbestoj , aŭ ĵetas ; la tria vorto estas pomoj , katoj , aŭ baseballs ; kaj la frazo finiĝas per punkto? Ĉi regex estu kazo-sensenta. Ĝi devas parigi la sekvaj:
sed ne la jenaj:
|
praktiko Projektoj
Por praktiko, skribi programojn por fari la sekvajn taskojn.
Forta Pasvorto Malkaŝo
Skribi funkcion kiu uzas regulajn esprimojn por certigi la pasvorton ŝnuro ĝi estas pasita estas forta. Forta
pasvorto difinita kiel unu kiu estas almenaŭ ok signojn longa, enhavas
ambaŭ majusklajn kaj minusklajn literojn, kaj havas almenaŭ unu cifero. Vi eble bezonas provi la ŝnuron kontraŭ multnombraj regex ŝablonoj validigi lian forton.
Regex Versio de strio ()
Skribi funkcio kiu prenas ŝnuron kaj faras la samon kiel la
strip()
kordoj metodo. Se
neniu alia argumentoj estas pasitaj aliaj ol la kordo por senvestigi,
tiam spaceto karakteroj estos forigita de la komenco kaj fino de la
kordo. Alie, la karakteroj specifitaj en la dua argumento al la funkcio estos forigita de la kordo.
[ 1 ] Cory Doctorow, "Jen kion TICs devus vere instruas infanoj: kiel fari regulajn esprimojn" Gardanto , decembro 4, 2012, http://www.theguardian.com/technology/2012/dec/04/ict-teach -kids-regula-esprimoj / .
Nenhum comentário:
Postar um comentário