Nuolatinė išraiška, kuri niekada neatitiks

Tai gali atrodyti kvailas klausimas, bet aš ilgai kalbėjau su kai kuriais savo kolegomis kūrėjais, ir tai skamba kaip juokingas dalykas galvoti apie tai.

Taigi, kas yra jūsų mintis - kaip atrodo regex, niekada neatitinka eilutės?

Keisti . Kodėl aš to noriu? Visų pirma, nes man įdomu galvoti apie tokią išraišką, ir, antra, todėl, kad man reikia scenarijaus.

Šiame scenarijuje apibūdinu žodyną kaip Dictionary<string, Regex> . Tai, kaip matote, yra eilutė ir išraiška.

Remiantis šiuo žodynu, sukuriu metodus, kurie naudoja šį žodyną kaip nuorodą tik į tai, kaip jie turėtų atlikti savo darbą, iš kurių vienas atitinka įprastas išraiškas analizuotame žurnalo faile.

Jei išraiška atitinka, įterpiamas kitas Dictionary<string, long> , kurio vertė grąžinama išraiška. Taigi, norint sugauti visus žurnalo pranešimus, kurie neatitinka žodyno išraiškos, sukūriau naują grupę, vadinamą „nežinoma“.

Viskas, kas neatitinka jokio kito, pridedama prie šios grupės. Tačiau tam, kad būtų užkirstas kelias „nežinomam“ žurnalo pranešimo nenuoseklumo (atsitiktinai) išraiška, turėjau sukurti tokią išraišką, kuri tikrai niekada nesutiktų, nesvarbu, kokia linija man suteikiama.

Taigi turite priežastį dėl šio „ne klausimo“ ...

93
12 нояб. nurodyta Florian Peschka 12 nov. 2009-11-12 18:46 '09, 18:46 PM 2009-11-12 18:46
@ 23 atsakymai

Tai iš tikrųjų yra gana paprasta, nors tai priklauso nuo / vėliavos * įgyvendinimo:

 $a 

Po linijos pabaigos atitiks simbolį a . Sėkmės.

Dėmesio:
Ši išraiška yra brangi - ji nuskaito visą eilutę, suras linijos pririšimo pabaigą ir tik tada neras ir negrąžins neigiamos rungtynės. (Išsamesnės informacijos rasite toliau esančioje pastaboje.)


* Iš pradžių aš nemanau daug apie daugiapakopę reguliariąsias išraiškas, kur $ taip pat atitinka eilutės pabaigą. Tiesą sakant, jis atitiks tuščią eilutę prieš pat naują eilutę, todėl įprastas „a“ tipo simbolis niekada nebus rodomas po $ .

56
12 нояб. Atsakymą pateikė Ferdinand Beyer lapkričio 12 d. 2009-11-12 18:51 '09 at 18:51 PM 2009-11-12 18:51

negative lookahead :

 >>> import re >>> x=r'(?!x)x' >>> r=re.compile(x) >>> r.match('') >>> r.match('x') >>> r.match('y') 

tai RE yra prieštaravimas, todėl niekada neatitiks nieko.

Pastaba:
„Python“ funkcijoje re.match () funkcija netiesiogiai įtraukia eilutės pradžią ( \A ) į įprastos išraiškos pradžią. Šis inkaras yra svarbus našumui: be jo bus išbandyta visa linija. Tie, kurie nenaudoja „Python“, norės aiškiai pridėti inkarą:

 \A(?!x)x 
62
04 дек. Alex Martelli atsakymas 04 Dec 2009-12-04 08:46 '09 8:46 am 2009-12-04 08:46

apžiūrėkite:

(?=a)b

Reguliarių išraiškų pradedantiesiems: teigiama prognozė (?=a) užtikrina, kad kitas simbolis yra a , bet nekeičia paieškos vietos (arba suderintoje eilutėje yra „a“). Dabar, kai kitas simbolis patvirtintas kaip a , likusi reguliarioji išraiška ( b ) atitinka tik kitą simbolį b . Taigi, ši įprastinė išraiška atitinka tik tuo atveju, jei simbolis yra ir a ir b .

32
12 нояб. Atsakymas pateikiamas Amarghosh 12 nov. 2009-11-12 18:56 '09, 18:56, 2009-11-12 18:56

a\bc , kur \b yra nulinio pločio išraiška, atitinkanti žodžio ribą.

Jis negali pasirodyti šio žodžio, kurį verčiame, viduryje.

28
12 нояб. Atsakyti Pavel Shved 12 nov. 2009-11-12 18:51 '09 at 18:51 PM 2009-11-12 18:51

$.

.^

$.^

(?!)

20
04 дек. atsakymas suteiktas Knio 04 Dec 2009-12-04 08:52 '09 8:52 am 2009-12-04 08:52

Vienas, kuris buvo praleistas:

 ^\b$ 

Jis negali sutapti, nes tuščioje eilutėje nėra žodžio ribos. Išbandyta „Python“ 2.5.

19
20 февр. Mark Byers atsakymas vasario 20 d 2010-02-20 20:29 '10, 20:29, 2010-02-20 20:29

Maksimali atitiktis

 a++a 

Bent vienas a po a seka bet koks skaičius a , negrąžinimas. Tada pabandykite suderinti kitą a .

arba nepriklausoma pagalbinė raiška

Tai prilygsta a+ įdėjimui į nepriklausomą lauką, po to kitą a .

 (?>a+)a 
10
12 нояб. Atsakymą pateikė Brad Gilbert , lapkričio 12 d. 2009-11-12 19:19 '09, 19:19, 2009-11-12 19:19

Jis veikia:

 $. 
9
12 нояб. Atsakymą pateikė Jerry Fernholz 12 nov. 2009-11-12 18:50 '09 18:50 2009-11-12 18:50

Perl 5.10 palaiko specialius valdymo žodžius, vadinamus veiksmažodžiais, kurie yra išdėstyti sekoje (*...) . (Palyginkite su (?...) specialiąja seka.) Tarp jų yra (*FAIL) veiksmažodis , kuris iš karto grąžinamas iš įprastinės išraiškos.

Atkreipkite dėmesį, kad veiksmažodžiai PCRE netrukus įgyvendinami, todėl galite juos naudoti PHP arba kitomis kalbomis naudodami PCRE biblioteką. (Tačiau negalite naudoti „Python“ ar „Ruby“. Jie naudoja savo variklį.)

9
05 дек. Atsakymą pateikė Kang Seonghoon, gruodžio 5 d. 2009-12-05 09:53 '09 9:53 val. 2009-12-05 09:53

Ką apie $^ arba gal (?!) ?

9
12 нояб. Atsakymą pateikė Bobas lapkričio 12 d. 2009-11-12 18:49 '09, 18:49 PM 2009-11-12 18:49
 \B\b 

\b atitinka žodžių ribas - padėtis tarp raidės a yra ne raidė (arba linijos riba).
\b yra jo papildymas - jis atitinka padėtį tarp dviejų raidžių arba tarp raidžių.

Kartu jie negali atitikti jokios padėties.

Taip pat žiūrėkite:

8
31 янв. Atsakymas pateikiamas Kobi sausio 31 d 2011-01-31 14:19 '11, 14:19, 2011-01-31 14:19

Greičiausias bus:

 r = re.compile(r'a^') r.match('whatever') 

„a“ gali būti bet koks nespecifinis simbolis („x“, „y“). „Knio“ įgyvendinimas gali būti šiek tiek švaresnis, tačiau tai bus greitesnė visoms linijoms, o ne pradedant bet kokiu pasirinktu simboliu, o ne „a“, nes jis neatitiks po pirmojo simbolio, o ne po antrojo šiais atvejais.

5
05 дек. atsakymą pateikė Adam Nelson 05 d. 2009-12-05 00:35 '09 0:35 2009-12-05 00:35

„Python“ to nepriims, tačiau „Perl“:

 perl -ne 'print if /(w\1w)/' 

Ši reguliari išraiška turėtų (teoriškai) stengtis suderinti begalinį (vienodą) skaičių w s, nes pirmoji grupė ( () s sugrįžta į save. Atrodo, kad Perl nepateikė jokių įspėjimų netgi use strict; use warnings; use strict; use warnings; , todėl manau, kad tai bent jau galioja, ir mano (minimalus) testavimas neatitinka nieko, todėl siunčiu jį už jūsų kritiką.

4
04 дек. Chris Lutz atsakymas, pateiktas gruodžio 4 d 2009-12-04 08:48 '09 8:48 2009-12-04 08:48

[^\d\D] arba (?=a)b arba a$a arba a^a

4
19 дек. Atsakymą pateikė Bart Kiers gruodžio 19 d. 2009-12-19 23:16 '09 23:16 2009-12-19 23:16

Tai neveiks „Python“ ir daugeliu kitų kalbų, tačiau įprasta išraiška „Javascript“ [] yra galiojanti simbolių klasė, kuri negali būti suderinta. Taigi, nepaisant to, kas įvedama:

 var noMatch = /^[]/; 

Man tai patinka geriau nei /$a/ , nes man jis aiškiai perduoda savo ketinimą. Ir kai jums to reikia, man reikia, nes man reikia atsargos dinamiškai sukomponuotam šablonui, paremtam naudotojo įvedimu. Kai šablonas yra neteisingas, turiu jį pakeisti šablonu, kuris neatitinka nieko. Supaprastinta, tai atrodo taip:

 try { var matchPattern = new RegExp(someUserInput); } catch (e) { matchPattern = noMatch; } 
3
14 авг. atsakymas pateikiamas neapibrėžta 14 rug. 2014-08-14 21:53 '14, 21:53, 2014-08-14 21:53

Manau, kad

 \Z RE FAILS! \A 

apima net atvejus, kai įprastinė išraiška apima vėliavą, pvz., MULTILINE, DOTALL ir tt

 >>> import re >>> x=re.compile(r"\Z RE FAILS! \A") >>> x.match('') >>> x.match(' RE FAILS! ') >>> 

Manau, kad (bet aš to ne išbandžiau), kad, nepaisant ilgio (> 0), linijos tarp \Z ir \A turėtų laikas nuo laiko būti pastovios.

2
10 дек. atsakymas duotas 10 dec. 2009-12-10 21:18 '09 21:18 2009-12-10 21:18

Gal tai?

 /$.+^/ 
2
04 дек. atsakymas duotas Dan Breen 04 dec. 2009-12-04 08:46 '09 8:46 am 2009-12-04 08:46

O kas, vietoj reguliarios išraiškos, tiesiog naudokite nurodymus visada, jei? Javascript:

 var willAlwaysFalse=false; if(willAlwaysFalse) { } else { } 
1
04 дек. Atsakymą pateikė Graviton 04 Dec. 2009-12-04 08:46 '09 8:46 am 2009-12-04 08:46
 (*FAIL) 

arba

 (*F) 

Naudodami PCRE ir PERL, galite naudoti šį valdymo veiksmažodį, dėl kurio modelis iš karto nepavyksta.

1
07 июня '14 в 4:05 2014-06-07 04:05 Kazimiero ir Hipolito atsakymas birželio 7 d. 14 d. 4:05 2014-06-07 04:05

Peržiūrėję kai kuriuos iš šių nuostabių atsakymų, @arantius komentaras (dėl laiko $x vs x^ vs (?!x)x ) šiuo metu priimtame atsakyme privertė mane norėti turėti kai kuriuos sprendimus iki šiol.

Naudodamas standartinį standartą @arantius 275k, Python atlikiau šiuos testus (v3.5.2, IPython 6.2.1).

Tl; DR: 'x^' ir 'x\by' yra greičiausias, kai koeficientas yra ne mažesnis kaip ~ 16, ir nepaisant @arantius (?!x)x aptikimo, (?!x)x buvo vienas iš lėtiausių (~ 37 kartus lėčiau). Todėl greičio klausimas, žinoma, priklauso nuo įgyvendinimo. Išbandykite save pagal savo numatytą sistemą, prieš pradėdami, jei greitis jums yra svarbus.

UPDATE: Matyt, yra didelis neatitikimas tarp sinchronizacijos 'x^' ir 'a^' . Jei norite gauti daugiau informacijos, žr. Šį klausimą ir ankstesnį redagavimą lėtesniam laikui, a ne x .

 In [1]: import re In [2]: with open('/tmp/longfile.txt') as f: ...: longfile = f.read() ...: In [3]: len(re.findall('\n',longfile)) Out[3]: 275000 In [4]: len(longfile) Out[4]: 24733175 In [5]: for regex in ('x^','.^','$x','$.','$x^','$.^','$^','(?!x)x','(?!)','(?=x)y','(?=x)(?!x)',r'x\by',r'x\bx',r'^\b$' ...: ,r'\B\b',r'\ZNEVERMATCH\A',r'\Z\A'): ...: print('-'*72) ...: print(regex) ...: %timeit re.search(regex,longfile) ...: ------------------------------------------------------------------------ x^ 6.98 ms ± 58.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ------------------------------------------------------------------------ .^ 155 ms ± 960 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ $x 111 ms ± 2.12 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ $. 111 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ $x^ 112 ms ± 1.14 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ $.^ 113 ms ± 1.44 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ $^ 111 ms ± 839 µs per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ (?!x)x 257 ms ± 5.03 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) ------------------------------------------------------------------------ (?!) 203 ms ± 1.56 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ (?=x)y 204 ms ± 4.84 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) ------------------------------------------------------------------------ (?=x)(?!x) 210 ms ± 1.66 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) ------------------------------------------------------------------------ x\by 7.41 ms ± 122 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ------------------------------------------------------------------------ x\bx 7.42 ms ± 110 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) ------------------------------------------------------------------------ ^\b$ 108 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ \B\b 387 ms ± 5.77 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) ------------------------------------------------------------------------ \ZNEVERMATCH\A 112 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) ------------------------------------------------------------------------ \Z\A 112 ms ± 1.38 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) 

Kai pirmą kartą pradėjau, pamiršau paskutines 3 išraiškas, todėl '\b' aiškinama kaip '\x08' , nugaros vietos simbolis. Tačiau, nustebęs, 'a\x08c' buvo greitesnis nei ankstesnis sparčiausias rezultatas! Kad būtų teisingas, jis vis dar tinka šiam tekstui, bet maniau, kad tai dar verta paminėti, nes nesu įsitikinęs, kodėl tai greičiau.

 In [6]: for regex in ('x\by','x\bx','^\b$','\B\b'): ...: print('-'*72) ...: print(regex, repr(regex)) ...: %timeit re.search(regex,longfile) ...: print(re.search(regex,longfile)) ...: ------------------------------------------------------------------------ y 'x\x08y' 5.32 ms ± 46.1 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) None ------------------------------------------------------------------------ x 'x\x08x' 5.34 ms ± 66.3 µs per loop (mean ± std. dev. of 7 runs, 100 loops each) None ------------------------------------------------------------------------ $ '^\x08$' 122 ms ± 1.05 ms per loop (mean ± std. dev. of 7 runs, 10 loops each) None ------------------------------------------------------------------------ \ '\\B\x08' 300 ms ± 4.11 ms per loop (mean ± std. dev. of 7 runs, 1 loop each) None 

Mano bandymų failas buvo sukurtas naudojant formulę „... Skaitymo turinys ir dublikatų linijos“ („Ubuntu 16.04“):

 $ ruby -e 'a=STDIN.readlines;275000.times do;b=[];rand(20).times do; b << a[rand(a.size)].chomp end; puts b.join(" "); end' < /usr/share/dict/words > /tmp/longfile.txt $ head -n5 /tmp/longfile.txt unavailable speedometer garbling Zambia subcontracted fullbacks Belmont mantra's pizzicatos carotids bitch Hernandez renovate leopard Knuth coarsen Ramada flu occupies drippings peaces siroccos Bartók upside twiggier configurable perpetuates tapering pint paralyzed vibraphone stoppered weirdest dispute clergy getup perusal fork nighties resurgence chafe 
1
04 нояб. atsakymas pateikiamas nivk 04 lapkričio. 2017-11-04 23:57 '17 at 11:57 2017-11-04 23:57
 '[^0-9a-zA-Z...]*' 

ir pakeiskite ... su visais spausdintais simboliais;). Tai skirta tekstiniam failui.

1
12 нояб. Drakosha atsakymas lapkričio 12 d 2009-11-12 18:50 '09 18:50 2009-11-12 18:50

Nešiojamas sprendimas, kuris nepriklauso nuo „regexp“ įgyvendinimo, yra tiesiog naudoti pastovią eilutę, kurią esate tikri, kad niekada nebus rodomi žurnalo pranešimuose. Pvz., Įveskite eilutę pagal šiuos dalykus:

 cat /dev/urandom | hexdump | head -20 0000000 5d5d 3607 40d8 d7ab ce72 aae1 4eb3 ae47 0000010 c5e2 b9e8 910d a2d9 2eb3 fdff 6301 c85f 0000020 35d4 c282 e439 33d8 1c73 ca78 1e4d a569 0000030 8aca eb3c cbe4 aff7 d079 ca38 8831 15a5 0000040 818b 323f 0b02 caec f17f 387b 3995 88da 0000050 7b02 c80b 2d42 8087 9758 f56f b71f 0053 0000060 1501 35c9 0965 2c6e 03fe 7c6d f0ca e547 0000070 aba0 d5b6 c1d9 9bb2 fcd1 5ec7 ee9d 9963 0000080 6f0a 2c91 39c2 3587 c060 faa7 4ea4 1efd 0000090 6738 1a4c 3037 ed28 f62f 20fa 3d57 3cc0 00000a0 34f0 4bc2 3067 a1f7 9a87 086b 2876 1072 00000b0 d9e1 6b8f 5432 a60e f0f5 00b5 d9ef ed6f 00000c0 4a85 70ee 5ec4 a378 7786 927f f126 2ec2 00000d0 18c5 46fe b167 1ae6 c87c 1497 48c9 3c09 00000e0 8d09 e945 13ce 7da2 08af 1a96 c24c c022 00000f0 b051 98b3 2bf5 4d7d 5ec4 e016 a50d 355b 0000100 0e89 d9dd b153 9f0e 9a42 a51f 2d46 2435 0000110 ef35 17c2 d2aa 3cc7 e2c3 e711 d229 f108 0000120 324e 5d6a 650a d151 bc55 963f 41d3 66ee 0000130 1d8c 1fb1 1137 29b2 abf7 3af7 51fe 3cf4 

Žinoma, tai nėra intelektualus iššūkis, bet labiau kaip juostų kanalų programavimas .

0
12 февр. Atsakymą pateikė hlovdal , vasario 12 d. 2010-02-12 13:26 '10, 08:26 PM 2010-02-12 13:26
 new Regex(Guid.NewGuid().ToString()) 

Sukuria raštą, kuriame yra tik raidiniai ir skaitmeniniai simboliai ir „ - “ (nė vienas iš jų nėra specialus reguliarus išraiška), tačiau statistiškai neįmanoma, kad ta pati eilutė būtų rodoma kažkur anksčiau (nes tai yra visas GUID taškas).

-4
12 февр. vasario 12 d 2010-02-12 19:40 '10, 19:40, 2010-02-12 19:40

Kiti klausimai, susiję su etikete arba Užduoti klausimą