JavaRush /Java Blog /Random-TL /RegEx: 20 maikling hakbang upang makabisado ang mga regul...
Artur
Antas
Tallinn

RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression. Bahagi 2

Nai-publish sa grupo
RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression. Part 1 Original dito Sa huling bahagi ay pinagkadalubhasaan namin ang pinakasimpleng regular na expression, at may natutunan na kami. Sa bahaging ito ay pag-aaralan natin ang bahagyang mas kumplikadong mga disenyo, ngunit maniwala ka sa akin, hindi ito magiging mahirap gaya ng tila. RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression.  Bahagi 2 - 1Kaya't magpatuloy tayo!

Hakbang 8: Star *at Plus Sign+

RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression.  Bahagi 2 - 2Sa ngayon, higit pa o mas kaunti pa lang ang naitugma namin sa mga string ng isang partikular na haba. Ngunit sa mga pinakahuling problema naabot namin ang limitasyon ng kung ano ang maaari naming gawin sa notasyon na nakita namin sa ngayon. Ipagpalagay natin, halimbawa, na hindi tayo limitado sa 3-character na Java identifier, ngunit maaari tayong magkaroon ng mga identifier ng anumang haba. Ang isang solusyon na maaaring gumana sa nakaraang halimbawa ay hindi gagana sa sumusunod na halimbawa:
pattern: [a-zA-Z_$]\w\w 
string:   __e $12 3 3.2 fo Bar r a23 mm ab x
mga tugma: ^^^ ^^^ ^^^ ^^^  
( Halimbawa ) talana kapag may bisa ang isang identifier ngunit mas mahaba sa 3 character, ang unang tatlong character lang ang itinutugma. At kapag ang identifier ay wasto, ngunit naglalaman ng mas mababa sa 3 mga character, pagkatapos ay hindi ito mahahanap ng regex! Ang problema ay ang mga naka-bracket na expression []ay tumutugma sa eksaktong isang character, tulad ng mga klase ng character tulad ng \w. Nangangahulugan ito na ang anumang mga tugma sa regular na expression sa itaas ay dapat na eksaktong tatlong character ang haba. Kaya hindi ito gumana nang maayos gaya ng inaasahan natin. *Ang mga espesyal na character at maaaring makatulong dito +. Ito ay mga modifier na maaaring idagdag sa kanan ng anumang expression upang tumugma sa expression na iyon nang higit sa isang beses. Ang Kleene Star (o "asterisk") *ay magsasaad na ang nakaraang token ay dapat na tumugma sa anumang bilang ng beses, kabilang ang mga zero na beses. Ang plus sign +ay magsasaad na kailangan mong maghanap ng isa o higit pang beses. Kaya, ang expression na nauuna +ay ipinag-uutos (kahit isang beses), habang ang expression na nauuna *ay opsyonal, ngunit kapag lumitaw ito, maaari itong lumitaw kahit ilang beses. Ngayon, sa kaalamang ito, maaari nating itama ang regular na expression sa itaas:
pattern: [a-zA-Z_$]\w* 
string:   __e $123 3.2 para sa Barr a23mm ab x 
na mga tugma: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ ^ 
( Halimbawa ) Ngayon ay tinutugma namin ang mga wastong identifier ng anumang haba! Bingo! Ngunit ano ang mangyayari kung ginamit natin +sa halip na *?
pattern: [a-zA-Z_$]\w+ 
string:   __e $123 3.2 para sa Barr a23mm ab x
mga tugma: ^^^ ^^^^ ^^ ^^^^ ^^^^^ ^^ 
( Halimbawa ) Na-miss namin ang huling laban, х. Ito ay dahil nangangailangan ito +ng hindi bababa sa isang character na itugma, ngunit dahil ang nakakulong na expression na []sinusundan \w+ay 'kinakain' na ang character x, wala nang mga character na magagamit, kaya nabigo ang tugma. Kailan natin magagamit +? Kapag kailangan nating maghanap ng kahit isang tugma, ngunit hindi mahalaga kung gaano karaming beses dapat tumugma ang isang naibigay na expression. Halimbawa, kung gusto naming makahanap ng anumang mga numero na naglalaman ng decimal point:
pattern: \d*\.\d+ 
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 
mga tugma: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^  
( Halimbawa ) talana sa pamamagitan ng paggawa ng mga numero sa kaliwa ng decimal point na opsyonal, nahanap namin ang parehong 0.011 at .2. Upang gawin ito, kailangan naming itugma ang eksaktong isang decimal point sa \.at kahit isang digit sa kanan ng decimal point na may \d+. Ang regular na expression sa itaas ay hindi tutugma sa isang numero tulad ng 3., dahil kailangan namin ng hindi bababa sa isang digit sa kanan ng decimal point upang tumugma.

Gaya ng dati, lutasin natin ang ilang simpleng problema:

Hanapin ang lahat ng mga salitang Ingles sa sipi sa ibaba.
pattern:
string: 3 plus 3 ay anim ngunit 4 plus three ay 7
mga tugma:    ^^^^ ^^ ^^^ ^^^ ^^^^ ^^^^^ ^^ 
( Solusyon ) Hanapin ang lahat ng mga simbolo ng laki ng file sa listahan sa ibaba. Ang mga laki ng file ay binubuo ng isang numero (mayroon o walang decimal point) na sinusundan ng KB, MB, GBo TB:
pattern:
string:   11TB 13 14.4MB 22HB 9.9GB TB 0KB 
na mga tugma: ^^^^ ^^^^^^ ^^^^^ ^^^  
( Solusyon )

Hakbang 9: "opsyonal" na tandang pananong?

RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression.  Bahagi 2 - 3Naisulat mo na ba ang regex upang malutas ang huling problema? Gumana ba? Ngayon subukang ilapat ito dito:
pattern:
string: 1..3KB 5...GB ..6TB
mga tugma:  
Malinaw, alinman sa mga pagtatalaga na ito ay isang wastong laki ng file, kaya ang isang mahusay na regular na expression ay hindi dapat tumugma sa alinman sa mga ito. Ang solusyon na isinulat ko upang malutas ang huling problema ay tumutugma sa kanilang lahat, hindi bababa sa bahagi:
pattern: \d+\.*\d*[KMGT]B 
string:   1..3KB  5...GB .. 6TB 
na mga tugma: ^^^^^^ ^^^^^^ ^^^ 
( Halimbawa ) Kaya ano ang problema? Sa katunayan, kailangan lang nating maghanap ng isang decimal point, kung mayroon man. Ngunit *pinapayagan nito ang anumang bilang ng mga tugma, kabilang ang zero. Mayroon bang paraan upang tumugma lamang sa zero na beses o isang beses? Ngunit hindi hihigit sa isang beses? Syempre meron. Ang "opsyonal" ?ay isang modifier na tumutugma sa zero o isa sa mga naunang character, ngunit wala na:
pattern: \d+\.?\d*[KMGT]B 
string: 1.. 3KB 5...GB .. 6TB 
na mga tugma:     ^^^ ^^^ 
( Halimbawa ) Mas malapit tayo sa isang solusyon dito, ngunit hindi ito ang kailangan natin. Makikita natin kung paano ito ayusin sa ilang hakbang mamaya.

Pansamantala, lutasin natin ang problemang ito:

Sa ilang mga programming language (hal. Java), ang ilang integer at floating point (tuldok) na numero ay maaaring sundan ng l/ Lat f/ Fupang ipahiwatig na dapat silang ituring na mahaba/float (ayon sa pagkakabanggit) sa halip na bilang regular na int/double. Hanapin ang lahat ng wastong "mahabang" numero sa linya sa ibaba:
pattern:
string:   13L ang haba 2l 19 L lL 0 
tugma: ^^^ ^^ ^^ ^ 
( Solusyon )

Hakbang 10: "o" sign|

RegEx: 20 maikling hakbang upang makabisado ang mga regular na expression.  Bahagi 2 - 4Sa hakbang 8, nahirapan kaming maghanap ng iba't ibang uri ng mga numero ng floating point:
pattern: \d*\.\d+ 
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 
mga tugma: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^  
Ang pattern sa itaas ay tumutugma sa mga numero na may isang decimal point at hindi bababa sa isang digit sa kanan ng decimal point. Ngunit paano kung gusto rin nating tumugma sa mga string tulad ng 0.? (Walang mga numero sa kanan ng decimal point.) Maaari tayong sumulat ng isang regular na expression tulad nito:
pattern: \d*\.\d* 
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. . 
mga tugma: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ ^ 
( Halimbawa ) Ito ay tumutugma 0., ngunit tumutugma din ito sa isang punto ., gaya ng makikita mo sa itaas. Sa totoo lang, ang sinusubukan naming itugma ay dalawang magkaibang klase ng string:
  1. mga numerong may hindi bababa sa isang digit sa kanan ng decimal point
  2. mga numerong may hindi bababa sa isang digit sa kaliwa ng decimal point
Isulat natin ang sumusunod na 2 regular na expression, na independyente sa isa't isa:
pattern: \d*\.\d+ 
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. .
mga tugma: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^  
pattern: \d+\.\d* 
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. .
mga tugma: ^^^^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ 
Nakikita namin na wala sa mga kasong ito ang mga substring 42, 5, 6o .matatagpuan ng makina. Upang makuha ang kinakailangang resulta, hindi namin masasaktan na pagsamahin ang mga regular na expression na ito. Paano natin ito makakamit? Ang "o" sign |ay nagpapahintulot sa amin na tukuyin ang ilang posibleng pagkakasunod-sunod ng mga tugma nang sabay-sabay sa isang regular na expression. Tulad []ng "o" sign na nagpapahintulot sa amin na tukuyin ang mga alternatibong solong character, |maaari naming tukuyin ang mga alternatibong multi-character na expression. Halimbawa, kung gusto naming maghanap ng "aso" o "pusa", maaari kaming sumulat ng ganito:
pattern: \w\w\w 
string:   Malinaw na mas mabuting alagang hayop ang aso kaysa pusa .
mga tugma: ^^^^^^^^^ ^^^ ^^^^^^ ^^^ ^^^ ^^^ 
( Halimbawa ) ... ngunit tumutugma ito sa lahat ng triple character sequence ng class na "word". Ngunit ang "aso" at "pusa" ay walang magkaparehong mga letra, kaya ang mga square bracket ay hindi makakatulong sa atin dito. Narito ang pinakasimpleng regular na expression na magagamit namin na tumutugma sa pareho at sa dalawang salitang ito lamang:
pattern: dog|cat 
string: Malinaw, ang aso ay mas mabuting alagang hayop kaysa pusa .
mga tugma:               ^^^ ^^^ 
( Halimbawa ) Sinusubukan muna ng regular na expression engine na itugma ang buong sequence sa kaliwa ng character |, ngunit kung nabigo ito, susubukan nitong itugma ang sequence sa kanan ng character |. |Maaari ding i-chain ang maramihang mga character upang tumugma sa higit sa dalawang alternatibong sequence:
pattern: dog|cat|pet 
string: Malinaw na mas mabuting alagang hayop ang aso kaysa pusa .
mga tugma:               ^^^ ^^^ ^^^ 
( Halimbawa )

Ngayon, lutasin natin ang isa pang pares ng mga problema para mas maunawaan ang hakbang na ito:

Gamitin ang sign |upang itama ang decimal na regular na expression sa itaas upang makagawa ng isang resulta tulad nito:
pattern:
string:   0.011 .2 42 2.0 3.33 4.000 5 6 7.89012 0. .
mga tugma: ^^^^^ ^^ ^^^ ^^^^ ^^^^^ ^^^^^^^ ^^ 
( Solusyon ) Gumamit ng sign |, mga klase ng character, "opsyonal" ?, atbp. upang lumikha ng isang regular na expression na tumutugma sa parehong mga numero ng integer at floating point (tuldok), tulad ng tinalakay sa problema sa dulo ng nakaraang hakbang (medyo ang problemang ito mas kumplikado, oo ;))
pattern:
string:   42L 12 x 3.4f 6l 3.3 0F LF .2F 0. 
mga tugma: ^^^ ^^ ^^^^ ^^ ^^^ ^^ ^^^ ^^  
( Solusyon ) 20 maikling hakbang upang makabisado ang mga regular na expression. Part 3 RegEx: 20 maiikling hakbang para makabisado ang mga regular na expression. Bahagi 4
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION