Įprastinė išraiška, atitinkanti eilutę, kurioje nėra žodžio?

Žinau, kad galite derinti žodį ir tada suderinti rungtynes ​​naudodami kitus įrankius (pvz., grep -v ). Tačiau norėčiau sužinoti, ar galima suderinti eilutes, kuriose nėra konkretaus žodžio (pvz., Hede), naudojant įprastą išraišką.

Įvestis:

 hoho hihi haha hede 

kodas:

 grep "<Regex for 'doesn't contain hede'>" input 

Privaloma išvestis:

 hoho hihi haha 
3715
02 янв. knaser yra nustatytas 02 jan. 2009-01-02 10:30 '09 10:30 val. 2009-01-02 10:30
@ 28 atsakymai

Sąvoka, kad reguliarioji išraiška nepalaiko atvirkštinio atitikimo, nėra visiškai teisinga. Galite imituoti šį elgesį naudodami neigiamus vaizdus:

 ^((?!hede).)*$ 

Aukščiau pateikta reguliarioji išraiška atitiks bet kokią eilutę arba eilutę, nepažeidžiant eilutės, kurioje nėra (pagal) eilutę „hede“. Kaip jau minėta, tai ne tai, ką reguliariai išreiškia „gera“ (ar turėtų daryti), bet vis dar įmanoma.

Jei taip pat reikia sujungti linijų pertraukas, naudokite DOT-ALL modifikatorių (galutinis s sekančiame pavyzdyje):

 /^((?!hede).)*$/s 

arba naudokite ją eilutėje:

 /(?s)^((?!hede).)*$/ 

(kur /.../ yra reguliarios išraiškos ribotojai, t. y. jie nėra modelio dalis)

Jei DOT-ALL modifikatorius nepasiekiamas, galite simuliuoti tą patį elgesį su simbolių klase [\s\S] :

 /^((?!hede)[\s\S])*$/ 

Aprašymas

Styga yra tik simbolių n sąrašas. Prieš ir po kiekvieno simbolio yra tuščia eilutė. Taigi ženklų n sąraše bus n+1 tuščios eilutės. Apsvarstykite eilutę "ABhedeCD" :

  ┌──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┬───┬──┐ S = │e1│ A │e2│ B │e3│ h │e4│ e │e5│ d │e6│ e │e7│ C │e8│ D │e9│ └──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┴───┴──┘ index 0 1 2 3 4 5 6 7 

kur e yra tuščios eilutės. Reguliari raiška (?!hede). tikimės, kad pamatysite, ar yra "hede" seka, ir jei taip (taip, kad kažkas būtų matoma) . (taškas) atitiks bet kokį simbolį, išskyrus eilutės pertrauką, „Look-arounds“ taip pat vadinami nulinio pločio pranešimais, nes jie nevartoja jokių simbolių. Jie tik patvirtina / patikrina kažką.

Taigi, mano pavyzdžiu, kiekviena tuščia eilutė pirmą kartą patikrinama, ar prieš tai, kai simbolis suvartojamas, yra "hede" . (visiškas sustojimas). Reguliari raiška (?!hede). tai padarys tik vieną kartą, taigi jis yra suvyniotas į grupę ir kartojamas nulis ar daugiau kartų: ((?!hede).)* . Galiausiai, įvesties pradžia ir pabaiga yra susietos, kad įsitikintumėte, jog visa įvestis sunaudojama: ^((?!hede).)*$

Kaip matote, įrašas "ABhedeCD" nepavyks su klaida, nes „ e3 “ pakartoja išraišką (?!hede) (yra "hede" į priekį!).

5054
02 янв. Atsakymas duotas Bartui Kiersui 02 sausio. 2009-01-02 12:55 '09, 12:55, 2009-01-02 12:55

Atkreipkite dėmesį, kad sprendimas prasideda ne „hede“ :

 ^(?!hede).*$ 

paprastai, daug efektyviau, nei sprendime nėra „hede“ :

border=0
 ^((?!hede).)*$ 

Pirmieji patikrina „hede“ tik pirmoje įvesties linijų padėtyje, o ne kiekvienoje padėtyje.

627
17 марта '11 в 7:21 2011-03-17 07:21 atsakymą pateikė JoshuaDavid, kovo 17 d. 11 d., 7:21 val. 2011-03-17 07:21

Jei tik naudosite jį grep, galite naudoti grep -v hede kad gautumėte visas linijas, kuriose nėra hede.

ETA Oh, po naujo klausimo, grep -v , tikriausiai reiškia „instrumentines parinktis“.

172
02 янв. atsakymas duotas Athena 02 jan. 2009-01-02 10:41 '09, 10:41 2009-01-02 10:41

Atsakymas:

 ^((?!hede).)*$ 

Paaiškinimas:

^ linijos pradžia, ( ir patraukite iki 1 (0 ar daugiau kartų (atitinkantį didžiausią galimą sumą)),
(?! Pažvelkite į priekį, kad pamatytumėte, ar tai yra,

hede jūsų eilutė

) laukimo pabaiga. bet koks simbolis, išskyrus \ t
)* pabaiga 1 (Pastaba: kadangi šiam užfiksavimui naudojate kiekybinį dydį, tik 1 \ t
$ iki pasirinktinio n ir eilutės pabaigos

129
10 мая '14 в 19:36 2014-05-10 19:36 atsakymą pateikė Jessica gegužės 10 d. 14, 19:36 2014-05-10 19:36

Šie atsakymai yra visiškai gražūs, tik akademiniai taškai:

Reguliarios išraiškos teorinių kompiuterių mokslo prasme NEGALIMA tai padaryti. Jiems tai turėtų atrodyti taip:

 ^([^h].*$)|(h([^e].*$|$))|(he([^h].*$|$))|(heh([^e].*$|$))|(hehe.+$) 

Tai atitinka tik FULL. Tai darant papildomas rungtynes ​​būtų dar labiau nepatogu.

93
02 сент. Atsakymas pateiktas Hades32 02 Sep. 2011-09-02 18:53 '11 at 18:53 2011-09-02 18:53

Jei norite, kad reguliarios išraiškos testas nepavyktų, tik tuomet, jei visos eilutės atitinka, veiks toliau:

 ^(?!hede$).* 

Pavyzdžiui, jei norite leisti visas vertes, išskyrus "foo" (ty "foofoo", "barfoo" ir "foobar", bet "foo" nepavyks), naudokite: ^(?!foo$).*

Žinoma, jei patikrinate tikslią lygybę, geriausias bendras sprendimas šiuo atveju yra patikrinti stygų lygybę, t.y.

 myStr !== 'foo' 

Jei reikia bet kokių reguliarių išraiškos funkcijų (čia, atvejo nejautrumo ir diapazono atitikimo), bandymui netgi galite padaryti neigiamą:

 !/^[af]oo$/i.test(myStr) 

Tačiau šio atsakymo viršuje esantis regex sprendimas gali būti naudingas tais atvejais, kai reikalingas teigiamas regex testas (galbūt naudojant API).

51
04 янв. atsakymą pateikė Roy Tinker 04 Jan 2013-01-04 00:22 '13 prie 0:22 2013-01-04 00:22

Čia yra geras paaiškinimas, kodėl nėra lengva paneigti savavališką reguliarią išraišką. Vis dėlto turiu sutikti su kitais atsakymais: jei tai yra kažkas, kas nėra hipotetinis klausimas, tada reguliarioji išraiška nėra tinkamas pasirinkimas.

49
02 янв. Josh Lee atsakymas, pateiktas sausio 02 d 2009-01-02 11:03 '09 at 11:03 2009-01-02 11:03

FWIW, nes reguliariai vartojamos kalbos (dar žinomos kaip racionalios kalbos) yra uždarytos papildymo atžvilgiu, visada galite rasti reguliarią išraišką (dar žinomą kaip racionali išraiška), kuri neigia kitą išraišką. Tačiau tai nėra daug įrankių.

„Vcsn“ palaiko šį teiginį (kuris reiškia „ {c} , postfix“).

Pirma, apibrėžiate savo išraiškų tipą: etiketės - raidė ( lal_char ), skirta pasirinkti nuo a iki z (pvz., Abėcėlės apibrėžtis, kai dirbama su priedu, žinoma, yra labai svarbi), ir kiekvienai žodžiui apskaičiuota „vertė“ yra tik logiška: true žodis priimtas , false , atmesta.

„Python“:

 In [5]: import vcsn c = vcsn.context('lal_char(az), b') c Out[5]: {a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z} → 𝔹 

tada įvesite savo frazę:

 In [6]: e = c.expression('(hede){c}'); e Out[6]: (hede)^c 

konvertuoti šią išraišką į automatą:

 In [7]: a = e.automaton(); a 

2019

05 авг. atsakymą pateikė akim 05 rug. 2015-08-05 10:02 '15 at 10:02 am 2015-08-05 10:02

Lyginamieji standartai

Nusprendžiau įvertinti kai kuriuos pateiktus variantus ir palyginti jų rezultatus bei naudoti keletą naujų funkcijų. „.NET Regex“ variklio lyginamoji analizė: http://regexhero.net/tester/

Valdymo tekstas:

Pirmosios 7 eilutės neturėtų sutapti, nes jose yra paieškos terminas, o apatinės 7 eilutės turi atitikti!

 Regex Hero is a real-time online Silverlight Regular Expression Tester. XRegex Hero is a real-time online Silverlight Regular Expression Tester. Regex HeroRegex HeroRegex HeroRegex HeroRegex Hero is a real-time online Silverlight Regular Expression Tester. Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her Regex Hero is a real-time online Silverlight Regular Expression Tester. Regex Her is a real-time online Silverlight Regular Expression Tester.Regex Hero egex Hero egex Hero egex Hero egex Hero egex Hero egex Hero Regex Hero is a real-time online Silverlight Regular Expression Tester. RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRegex Hero is a real-time online Silverlight Regular Expression Tester. Regex Her egex Hero egex Hero is a real-time online Silverlight Regular Expression Tester. Regex Her is a real-time online Silverlight Regular Expression Tester. Regex Her Regex Her Regex Her Regex Her Regex Her Regex Her is a real-time online Silverlight Regular Expression Tester. Nobody is a real-time online Silverlight Regular Expression Tester. Regex Her o egex Hero Regex Hero Reg ex Hero is a real-time online Silverlight Regular Expression Tester. 

Rezultatai:

Rezultatai - Iteracijos per sekundę, kai mediana yra 3 kartus

 01: ^((?!Regex Hero).)*$ 3.914 // Accepted Answer 02: ^(?:(?!Regex Hero).)*$ 5.034 // With Non-Capturing group 03: ^(?>[^R]+|R(?!egex Hero))*$ 6.137 // Lookahead only on the right first letter 04: ^(?>(?:.*?Regex Hero)?)^.*$ 7.426 // Match the word and check if you're still at linestart 05: ^(?(?=.*?Regex Hero)(?#fail)|.*)$ 7.371 // Logic Branch: Find Regex Hero? match nothing, else anything P1: ^(?(?=.*?Regex Hero)(*FAIL)|(*ACCEPT)) ????? // Logic Branch in Perl - Quick FAIL P2: .*?Regex Hero(*COMMIT)(*FAIL)|(*ACCEPT) ????? // Direct COMMIT  FAIL in Perl 

Kadangi .NET nepalaiko veiksmažodžių veiksmo (* FAIL ir tt), negalėjau patikrinti sprendimų P1 ir P2.

Santrauka:

Bandžiau išbandyti daugumą siūlomų sprendimų, kai kurie žodžiai gali būti optimizuoti. Pvz., Jei pirmosios dvi paieškos eilutės raidės nesutampa, atsakymas 03 gali būti išplėstas į ^(?>[^R]+|R+(?!egex Hero))*$ , dėl kurio šiek tiek padidėja našumas.

Vis dėlto, atrodo, kad bendras labiausiai skaitomas ir greitai veikiantis sprendimas turi reikšmę 05, naudojant sąlyginę išraišką arba 04 su tikėtinu kiekybiniu dydžiu. Manau, kad „Perl“ sprendimai turėtų būti greitesni ir aiškesni.

41
13 авг. Falco rugpjūčio 13 d. Atsakymas 2014-08-13 17:58 '14, 17:58, 2014-08-13 17:58

Neigiama išvaizda, reguliarioji išraiška gali atitikti kažką, kuriame nėra konkretaus modelio. Tai atsakė ir paaiškino Bart Kirs. Puikus paaiškinimas!

Tačiau, atsakydamas į Bart Kirs, kontrolinė dalis patikrins nuo 1 iki 4 simbolių prieš tai, kai suderinsite visus simbolius. Galime to išvengti ir leisti, kad apžvalgos dalis patikrintų visą tekstą, užtikrintų, kad nėra „hede“, o tada - normalios dalies (. *) Vienu metu galima valgyti visą tekstą.

Čia yra patobulinta reguliari raiška:

 /^(?!.*?hede).*$/ 

Atkreipkite dėmesį, kad (*?) Neigiamoje apžvalgoje neigiamo kiekio nustatymo priemonė yra neprivaloma, vietoj to galite naudoti (*) gobšus kiekybą, priklausomai nuo jūsų duomenų: jei pusė teksto pradžioje yra hede, tingus kiekybininkas gali būti greitesnis; kitaip gobšus kiekybininkas bus greitesnis. Tačiau jei „hede“ nėra, abu bus vienodai lėtai.

Čia yra demono kodas.

Norėdami gauti daugiau informacijos apie „lookahead“, žr. Puikų straipsnį: „ Mastering Lookahead“ ir „Lookbehind“ .

Taip pat patikrinkite „ RegexGen.js“ , „JavaScript“ reguliarios išraiškos generatorius, kuris padeda sukurti sudėtingas reguliariąsias išraiškas. Naudodamiesi „RegexGen.js“ galite sukurti paprastesnę išraišką suprantamesniu būdu:

 var _ = regexGen; var regex = _( _.startOfLine(), _.anything().notContains( // match anything that not contains: _.anything().lazy(), 'hede' // zero or more chars that followed by 'hede', // ie, anything contains 'hede' ), _.endOfLine() ); 
39
14 июля '14 в 21:21 2014-07-14 21:21 atsakymą pateikė amobizas liepos 14 d., 14 val. 21:21 2014-07-14 21:21

Ne reguliari išraiška, bet man buvo logiška ir naudinga naudoti nuoseklius grepsus su vamzdeliu, kad būtų pašalintas triukšmas.

Pavyzdžiui. ieškoti apache konfigūracijos failo be komentarų -

 grep -v '\#' /opt/lampp/etc/httpd.conf # this gives all the non-comment lines 

ir

 grep -v '\#' /opt/lampp/etc/httpd.conf | grep -i dir 

Sekvencinė grep logika (ne komentaras) ir (atitinka dir)

32
23 февр. Atsakymą pateikia kiwalk vasario 23 d 2011-02-23 17:00 '11 17:00 val. 2011-02-23 17:00

kol išvengsite kiekvieno pozicijos peržiūros:

 /^(?:[^h]+|h++(?!ede))*+$/ 

lygiavertis (for.net):

 ^(?>(?:[^h]+|h+(?!ede))*)$ 

Senas atsakymas:

 /^(?>[^h]+|h+(?!ede))*$/ 
28
14 апр. atsakymas, kurį pateikė Casimir et Hippolyte 2013-04-14 06:04 '13, 6:04 2013-04-14 06:04

Štai kaip tai padaryti:

 ^[^h]*(h(?!ede)[^h]*)*$ 

Tikslus ir veiksmingas nei kiti atsakymai. Jis įgyvendina „Friedl“ išsikabinimo metodą ir reikalauja daug mažiau grąžos.

18
20 дек. atsakymas duotas ridgerunner 20 d. 2013-12-20 06:03 '13, 6:03, 2013-12-20 06:03

Pirmiau minėtas (?:(?!hede).)* Puikus, nes jis gali būti susietas.

 ^(?:(?!hede).)*$ # A line without hede foo(?:(?!hede).)*bar # foo followed by bar, without hede between them 

Tačiau šiuo atveju pakanka:

 ^(?!.*hede) # A line without hede 

Šis supaprastinimas yra pasirengęs pridėti „AND“ nuostatas:

 ^(?!.*hede)(?=.*foo)(?=.*bar) # A line with foo and bar, but without hede ^(?!.*hede)(?=.*foo).*bar # Same 
17
23 авг. Atsakymas, kurį pateikė ikegami rugpjūčio 23 d 2016-08-23 03:03 '16 at 3:03 2016-08-23 03:03

Jei norite sujungti simbolį, panaikinti žodį, panašų į neigiamą simbolių klasę:

Pavyzdžiui, eilutė:

 <? $str="aaa bbb4 aaa bbb7"; ?> 

Nenaudokite:

 <? preg_match('/aaa[^bbb]+?bbb7/s', $str, $matches); ?> 

Naudoti:

 <? preg_match('/aaa(?:(?!bbb).)+?bbb7/s', $str, $matches); ?> 

Pastaba "(?!bbb)." nei žvilgsnis, nei žvilgsnis nėra, tai atrodo kaip dabartinis, pavyzdžiui:

 "(?=abc)abcde", "(?!abc)abcde" 
16
23 марта '12 в 10:24 2012-03-23 10:24 atsakymas pateikiamas diizmui kovo 23 d., 12 val. 10:24 val. 2012-03-23 ​​10:24

OP nenurodė žyma arba pranešimo, kuriame būtų nurodytas kontekstas (programavimo kalba, redaktorius, įrankis), kuriame bus naudojamas „Regex“.

Man kartais reikia tai padaryti, redaguojant failą naudojant „ Textpad .

Textpad palaiko tam tikrą „Regex“, bet nepalaiko „lookahead“ ar „lookbehind“, todėl reikia atlikti kelis veiksmus.

Jei noriu išsaugoti visas eilutes, kuriose NĖRA eilutė, norėčiau tai padaryti taip:

1. Raskite / pakeiskite visą failą, kad pridėtumėte unikalią žymą kiekvienos eilutės, kurioje yra bet koks tekstas, pradžioje.

  Search string:^(.) Replace string:<@#-unique-#@>\1 Replace-all 

2. Ištrinkite visas eilutes, kuriose yra eilutė hede (pakeitimo eilutė tuščia):

  Search string:<@#-unique-#@>.*hede.*\n Replace string:<nothing> Replace-all 

3. Šiame etape visos likusios NE eilutės turi eilutę hede . Ištrinkite unikalią „žymę“ iš visų linijų (pakeitimo eilutė tuščia):

  Search string:<@#-unique-#@> Replace string:<nothing> Replace-all 

Dabar jūs turite kodą su visomis eilutėmis, kuriose yra eilutė.


Jei aš ieškosiu ko nors kito, tik stygos, kuriose NĖRA eilutė hede , norėčiau tai padaryti taip:

1. Raskite / pakeiskite visą failą, kad pridėtumėte unikalią žymą kiekvienos eilutės, kurioje yra bet koks tekstas, pradžioje.

  Search string:^(.) Replace string:<@#-unique-#@>\1 Replace-all 

2. Visoms eilutėms, kuriose yra eilutė, panaikinkite unikalų „žymę“:

  Search string:<@#-unique-#@>(.*hede) Replace string:\1 Replace-all 

3. Šiame etape visos eilutės, prasidedančios unikalia „žyma“, NĖRA eilutės hede . Dabar aš galiu padaryti kažką kitą tik šioms linijoms.

4. Kai baigsiu, ištrinu unikalią „žymą“ iš visų eilučių (pakeitimo eilutė tuščia):

  Search string:<@#-unique-#@> Replace string:<nothing> Replace-all 
12
27 апр. Kevino Fegano atsakymas, pateiktas balandžio 27 d 2013-04-27 01:28 '13 ne 1:28 2013-04-27 01:28

Nuo rubino-2.4.1 įvedimo mes galime naudoti naują Absent Operator reguliariai Rubys'o išraiškose

iš oficialaus dok

 (?~abc) matches: "", "ab", "aab", "cccc", etc. It doesn't match: "abc", "aabc", "ccccabc", etc. 

Taigi jūsų atveju ^(?~hede)$ užduotis atliekama jums

 2.4.1 :016 > ["hoho", "hihi", "haha", "hede"].select{|s| /^(?~hede)$/.match(s)} => ["hoho", "hihi", "haha"] 
8
23 марта '17 в 16:42 2017-03-23 16:42 atsakymą pateikė aelor kovo 17 d. 17 val. 16:42 2017-03-23 ​​16:42

Per veiksmažodį PCRE (*SKIP)(*F)

 ^hede$(*SKIP)(*F)|^.*$ 

Tai visiškai praleidžia eilutę, kurioje yra tiksli linija ir atitinka visas likusias eilutes.

Demo

Vykdymo dalys:

Apsvarstykite aukščiau nurodytą reguliarią išraišką, padalijus ją į dvi dalis.

  • Ant simbolio esanti dalis | . Dalis neturėtų būti tokia pati .

     ^hede$(*SKIP)(*F) 
  • Dalis po simbolio | . Dalis turi būti suderinta.

     ^.*$ 

1 DALIS

Regex variklis pradės vykdyti pirmąją dalį.

 ^hede$(*SKIP)(*F) 

Paaiškinimas:

  • ^ Manoma, kad esame pradžioje.
  • hede rungtynės hede
  • $ Nurodo, kad esame linijos pabaigoje.

Taigi, eilutė, kurioje yra eilutė hede bus suderinta. Kai tik įprastas išraiškos mechanizmas mato tokius (*SKIP)(*F) (Pastaba: galite rašyti (*F) kaip (*FAIL) veiksmažodį, jis praleis ir prilygsta rungtynėms. | yra vadinamas pakeitimu arba loginiu AR operatoriumi, pridėtu šalia PCRE veiksmažodžio, kuris inturn atitinka visas ribas, kurios yra tarp kiekvienos simbolio visose eilutėse, išskyrus tai, kad eilutėje yra tiksli eilutė. Žiūrėkite demonstraciją čia . Tai reiškia, kad jis bando suderinti likusios eilutės simbolius. Dabar bus vykdoma reguliarioji išraiška antroje dalyje.

2 DALIS

 ^.*$ 

Paaiškinimas:

  • ^ Manoma, kad esame pradžioje. t.y. jis atitinka visus styginių kelius, išskyrus vieną eilutėje. Žiūrėkite demonstraciją čia .
  • .* Daugialypiu režimu . atitiks bet kokį simbolį, išskyrus naują eilutę arba vežimą. Ir * pakartoja ankstesnį simbolį nulis ar daugiau kartų. Taigi, .* Susitiks su visa linija. Žiūrėkite demonstraciją čia .

    Sveiki, kodėl pridėjote. vietoj to. +?

    Nes .* Susitiks su tuščia eilute, bet .+ Neatitiks vietos. Mes norime suderinti visas linijas, išskyrus hede , galbūt ir tuščių eilučių galimybė. todėl turėtumėte naudoti .* vietoj .+ . .+ pakartojo ankstesnį simbolį vieną ar kelis kartus. Žiūrėkite. .* Čia atitinka tuščią eilutę.

  • $ Nėra reikalo užpildyti linijos įpareigojimo.

8
09 окт. atsakymas duotas Avinash Raj 09 okt. 2014-10-09 10:00 '14 10:00 val. 2014-10-09 10:00

Kadangi niekas kitas neatsakė į pateiktą klausimą, tai padarysiu.

Atsakymas yra tas, kad POSIX grep neįmanoma tiesiogine prasme patenkinti šio prašymo:

 grep "Regex for doesn't contain hede" Input 

Priežastis yra ta, kad POSIX grep reikia tik darbui su pagrindinėmis reguliariomis išraiškomis , kurios paprasčiausiai nėra pakankamai veiksmingos, kad galėtų atlikti šią užduotį (jos negali analizuoti įprastų kalbų dėl pakaitos ir grupavimo trūkumo).

Tačiau GNU grep įgyvendina plėtinius, kurie tai leidžia. Visų pirma, \| yra GNU BRE diegimo pakaitinis operatorius, ir \( ir \) yra grupuojantys operatoriai. Jei jūsų įprastinė išraiška variklis palaiko plyšimą, neigiamus skliaustelius, grupavimą ir „Kleene“ žvaigždę ir sugeba prisirišti prie eilutės pradžios ir pabaigos, jums reikia tik šiam požiūriui.

Su GNU grep tai būtų kažkas panašaus:

 grep "^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" Input 

(su Gralu ir kai kuriais papildomais rankiniais optimizavimais).

Taip pat galite naudoti įrankį, kuris įgyvendina išplėstines reguliariąsias išraiškas , pvz., egrep , kad pašalintų grįžtamąjį sluoksnį:

 egrep "^([^h]|h(h|eh|edh)*([^eh]|e[^dh]|ed[^eh]))*(|h(h|eh|edh)*(|e|ed))$" Input 

Čia yra scenarijus, skirtas jį išbandyti (atkreipkite dėmesį, kad jis generuoja testinput.txt failą dabartiniame kataloge):

 #!/bin/bash REGEX="^\([^h]\|h\(h\|eh\|edh\)*\([^eh]\|e[^dh]\|ed[^eh]\)\)*\(\|h\(h\|eh\|edh\)*\(\|e\|ed\)\)$" # First four lines as in OP testcase. cat > testinput.txt <<EOF hoho hihi haha hede h he ah head ahead ahed aheda ahede hhede hehede hedhede hehehehehehedehehe hedecidedthat EOF diff -s -u <(grep -v hede testinput.txt) <(grep "$REGEX" testinput.txt) 

Mano sistemoje jis spausdina:

 Files /dev/fd/63 and /dev/fd/62 are identical 

kaip tikėtasi.

Tiems, kurie domisi detalėmis, naudojamas būdas reguliariai išreikšti žodį atitinkančią išraišką į baigtinę būsenos mašiną, o po to apversti būsenos mašiną, pakeisdami kiekvieną priėmimo būseną, kad atmestų ir atvirkščiai, ir tada konvertuojant gautą FA atgal į įprastą išraišką.

Galiausiai, kaip visi pažymėjo, jei jūsų įprastinė išraiška variklis palaiko neigiamą vaizdą, tai labai supaprastina užduotį. Pavyzdžiui, su GNU grep:

 grep -P '^((?!hede).)*$' Input 

Atnaujinimas: neseniai rasta Kendall Hopkins puikios FormalTheory bibliotekos, parašytos PHP, kuri suteikia funkcionalumą, panašų į Grail. Naudodamas šį ir supaprastintą tekstą, aš galėjau parašyti neigiamą reguliarių išraiškų internete generatorių su įvesties fraze (tik šiuo metu palaikomi raidiniai ir skaitmeniniai ir tarpmiestiniai ženklai): http://www.formauri.es/personal/pgimeno / kitokia / nereguliari reguliari išraiška /

hede jis atspausdina:

 ^([^h]|h(h|e(h|dh))*([^eh]|e([^dh]|d[^eh])))*(h(h|e(h|dh))*(ed?)?)?$ 

kuris yra lygiavertis aukščiau nurodytam.

7
07 дек. Atsakymas į Pedro Gimeno gruodžio 7 d 2016-12-07 00:24 '16 at 0:24 2016-12-07 00:24

Jis gali būti labiau paremtas dviem reguliariomis jūsų kodo išraiškomis, po vieną pirmai rungtynei, o tada, jei jis atitinka paleistį, antrasis reguliarus išraiška tikrina atvejus, kuriuos norite blokuoti, pvz., ^.*(hede).* , tada jūsų kode yra tinkama logika.