3 erilaista sulkumerkkiä: Oletko RegEx-mestari? | Rajoittamattomat järjestelmät (2023)

Jos olet käyttänyt jonkin aikaa koodin kirjoittamiseen, olet epäilemättä käyttänyt väärin säännöllisiä lausekkeita, kunnes niistä muodostui käsittämätön merkkiseka, joka voisi antaa oikean jäsentimen ansaita rahaa. Siitä huolimatta olin silti yllättynyt, kun sain tietää, että säännöllisissä lausekkeissa on 3 erilaista sulkumerkkiä, ei vain kahta.

Ja ei, ne 2 eivät ole vasen ja oikea, viisas kaveri.

Kolme sulkutyyppiä ovat kirjaimelliset, sieppaavat ja ei-kaappaavat. Tiedät luultavasti sulkeiden kaappaamisesta. Tunnistat myös kirjaimelliset sulut. Useimmat ihmiset jättävät sieppaamattomat sulkeet sekä useiden ja sisäkkäisten sieppaussulkujen ympärillä oleva semantiikka. (Todelliset RegEx-mestarit, pidä ”Mutta odota, siellä on enemmän!” -näppäintä lopuksi).

Kirjaimelliset sulkumerkit ovat juuri sitä kirjaimellista tekstiä, jota haluat yhdistää. Oletetaan, että haluat täsmäyttää lomakkeen yhdysvaltalaiset puhelinnumerot(xxx)yyy-zzzz. Voit kirjoittaa säännöllisen lausekkeen muodossa/\(\d{3})\d{3}-\d{4}/. Huomaa, että meidän piti kirjoittaa\(pelkän alaston sijaan(. Tämä johtuu siitä, että raakasulut käynnistävät sieppaavan tai ei-kaappaavan ryhmän. Jos haluamme löytää tekstin kirjaimellisen sulkumerkin, meidän on vältettävä sitä\.

Olet luultavasti kirjoittanut myös sieppaavia sulkeita, halusitpa sitten kaapata tai et. Näitä sulkeita ei käytetä vastaamaan kirjaimellista()tekstissä, mutta sen sijaan niitä käytetään ryhmittelemään merkkejä yhteen säännölliseen lausekkeeseen, jotta voimme käyttää muita operaattoreita, kuten+,*,?, tai{n}.

Jos esimerkiksi haluamme täsmäyttää vain merkkijonotvoitaiei voivoimme kirjoittaa/ei voi (ei)?/. Tarvitsemme sulkeita tähän, koska/ei voi?/vastaisi vain merkkijonojavoi', jaei voi, ei aivan sitä mitä meillä oli mielessä.

3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (1)

Tässä on kuitenkin jotain muuta meneillään. Näitä kutsutaan suluiksi sieppaamiseksi syystä —niin ne kuvaavat kaiken, mikä vastaa niiden sisältämää lauseketta myöhempää käyttöä varten. Jatkamme esimerkkiä voi/ei voi, JavaScriptissä saamme:

const match = /can('t)?/.exec("Emme voi tehdä sitä!"); console.log(match[0]); // tulostaa haun "ei voi" console.log(match[1]); // tulostaa kaapatun "'t"

Tässä,ottelu[1]sisältää suluissa olevan kohteen. Nyt tämä on jokseenkin epäkiinnostavaa, koska emme todellakaan välitä siitä‘tsanasta erilläänei voi.

Puhelinnumeroesimerkki muuttuu mielenkiintoisemmaksi. JavaScriptissä voimme poimia yhdysvaltalaisen puhelinnumeron suuntanumeron seuraavasti:

const match = /\((\d{3})\)\d{3}-\d{4}/.exec("(303)555-1212");console.log(match[0]); // (303)555-1212console.log(match[1]); // 303

Katsotaanpa tarkemmin, mitä tässä säännöllisessä lausekkeessa tapahtuu,/\((\d{3})\)\d{3}-\d{4}/. Se on melkein identtinen lausekkeen kanssa, jota käytimme kirjaimellisten sulkeiden esimerkissä, mutta tällä kertaa lisäsin joukon sieppaussulkuja kirjaimellisten sulkeiden pariin. Tämä käskee säännöllisen lausekkeen moottorin muistamaan sen osuman osan, joka on sieppaussuluissa. Löydämme tämän kaapatun ottelunottelu[1]. Huomaa, että koko puhelinnumero vastaaottelu[0]. Tämä pieni esimerkki osoittaa sulkeiden kaappaamisen voiman. Yllä käytimme sitä suuntanumeron poimimiseen puhelinnumerosta. Voimme käyttää sitä kaikenlaisen tekstin poimimiseen – köyhän miehen jäsentimen.

3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (2)

XKCD "Äidin hyväksikäytöt"

Toisena nopeana esimerkkinä voimme käyttää sulkujen kaappaamista etu- ja sukunimen poimimiseksi kautta/(\D+) (\D+)/.ottelu[1]on etunimi jaottelu[2]on sukunimi, jos et vastaa Bobby Tablesin etunimeä (katso sarjakuva), tai sinulla on ylimääräisiä välilyöntejä käsitelläksesi.

Nyt päästään kolmanteen sulkutyyppiin—ei-kaappaaviin sulkeisiin. Joskus sinun on ryhmiteltävä asiat yhteen säännölliseen lausekkeeseen, mutta et halua kaapata osumaa, kuten yllä olevassa can/not-esimerkissä. Välttääksesi sieppaamisen‘t, me kirjoitamme/voi(?:'t)?/. Täällä saamme vain koko ottelun ilman alaotteluita.

The(?:on erityinen sarja, joka aloittaa suluissa olevan ryhmän, aivan kuten(, mutta säännöllisen lausekkeen moottorille kerrotaan, älä vaivaudu kaappaamaan osumaa ryhmässä, vaan käytä sitä operaattorin etusijalla. Katsotaanpa monimutkaisempaa esimerkkiä, jossa suluissa olevan ryhmän huomiotta jättäminen on hyödyllistä.

Laajennetaan tätä puhelinnumeron säännöllistä lauseketta sallimaan etuliitemobiilitaitoimisto. Tämä näyttää tältä, kun kaappaa vain sulkeitamatch = /((mobiili|toimisto) )?\((\d{3})\)\d{3}-\d{4}/.exec(...). (Onko tämä vielä tutkimaton?). Ongelmana on, että suuntanumero, jonka haluamme poimia, on sisälläottelu[3]. (Jätän sen lukijalle harjoitukseksi miksi.) Tämä on hämmentävää ja tarpeetonta, koska emme välitä huomautuksesta tai mistään muusta kuin suuntanumerosta tässä esimerkissä. Voit kaapata vain suuntanumeron seuraavasti:

const re = /(?:(?:mobiili|toimisto) )?\((\d{3})\)\d{3}-\d{4}/;const match = re.exec('mobiili () 303)555-1212');console.log(match[0]); //mobiili (303)555-1212console.log(match[1]); //303

Huomaa kaksi ei-kaappaavaa sulkusarjaa(?:huomautuksen ympärillä, mutta suuntanumeron ympärillä käytetään tavallisia sieppaussulkuja.

Jotkut ihmiset ajattelevat, kun he kohtaavat ongelman
"Tiedän, käytän säännöllisiä lausekkeita."
Nyt heillä on kaksi ongelmaa.

JamieZawinksi

Ja siinä on se, 3 erilaista sulkumerkkiä, kirjaimellinen, sieppaava ja ei-kaappaava -\(,(,(?:. Pitäisi varmaan käyttää(?:enemmän kuin me, mutta minun on vaikea lukea, niin kauan kuin(ei aiheuta suorituskykyongelmia tai semanttisia muutoksia olemassa olevaan säännölliseen lausekkeeseen (muuttamalla hakemistoa, joka tarvitaan osuvien ryhmäosumien löytämiseen), ohitan ylimääräisen?:. En ole varma, onko tämä paras käytäntö, mutta totta puhuen, säännöllisiä lausekkeita on tarpeeksi vaikea lukea sellaisenaan.

Todelliset RegEx-päälliköt tietävät, että on olemassa muitakin sulkutyyppejä, jotka käyttävät(?myös syntaksi. Valitettavasti en ole säännöllisten lausekkeiden mestari, joten jätän sinun etsimään muita lähteitä saadaksesi tietoa niistä, koska niitä ei tueta monissa alkuperäisissä säännöllisten lausekkeiden kirjastoissa, JavaScript on yksi niistä.Nimetyt säännölliset lausekeryhmätovat näistä hyödyllisimpiä.

10 kommenttia
  1. 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (3)

    David Awerbuch

    6. marraskuuta 2018Vastaa

    Sulkeet voivat olla hieman hämmentäviä; tämä oli loistava artikkeli ja selkeästi selitetty sulujen sieppaamisesta ja ei-kaappaamisesta - enkä ollut tietoinen sieppaamatta jättämisestä.

    Joten minun pitäisi pystyä käyttämään yllä olevia tietoja helposti ongelman ratkaisemiseen - minun on muutettava nimi/arvo-pari, joka näyttää tältä "nimi(kolmen sanan arvo)" muotoon "nimi('kolmen sanan arvo')", jotta se voi lähetetty uudelleen komentoprosessorille.

    Pystyn kaappaamaan tekstin sulujen kääreestä, mutta sieppaus näyttää ulottuvan sulkevan sulkeen ohi datan loppuun.

    echo "DEFTYPE(PREDEFINED) DESCR(Administration Command Queue) DISTL(NO) GET(ENABLED)" \
    | sed -r "s/DESCR\((.*?)\)/DESCR('\1')/"

    tuottaa

    DEFTYPE(PRREDEFINED) DESCR('Administration Command Queue) DISTL(NO) GET(ENABLED')

    En näytä saavan eristettyä tekstiä, sulkumerkki sijoitetaan loppuun ennen viimeistä sulkusulkua, vaikka etsinkin lyhintä esiintymää käyttämällä '?'-merkkiä. Voitko auttaa minua täällä?

    Kiitos!

  • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (4)

    Manish Vachharajani

    6. marraskuuta 2018Vastaa

    Ongelmana on, että sed vastaa ahneesti (löytää suurimman vastaavuuden) ja vastaa siten GET:n (ENABLED) sulkevaan yläpäähän. Voit nähdä tämän poistamalla viimeisen merkin kaikutusta merkkijonosta ja näet, että lainaus lisätään heti DISTL(NO.

    echo "DEFTYPE(ESIMÄÄRITETTY) DESCR(Administration Command Queue) DISTL(NO) GET(ENABLED" | sed -r "s/DESCR\((.*?)\)/DESCR('\1')/"

    tuottaa

    DEFTYPE(PRREDEFINED) DESCR('Administration Command Queue) DISTL(EI') GET(ENABLED)

    Haluat, että ei-ahne haku vastaa lähimpään alkupäätä. En näe sed-asetusta ei-ahnevastaavuuden mahdollistamiseksi, mutta voit muuttaa säännöllistä lauseketta etsimään ) DISTL, jos se on aina olemassa. Jos ei, voit käyttää ei-ahnetta (vastahakoista) hakua Perlissä. Katsohttps://stackoverflow.com/questions/1103149/non-greedy-reluctant-regex-matching-in-sed

    • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (5)

      Jack Zinn

      27. marraskuuta 2018Vastaa

      Käytä "[^)]*" ".*?" sijaan siepata seuraavaan sulkumerkkiin asti.

  • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (6)

    Jack Zinn

    27. marraskuuta 2018Vastaa

    Muuta ".*?" kohtaan "[^)]*". Tämä tallentaa kaiken, kunnes painat sulkevia sulkeita.

  • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (7)

    roomalainen

    18. helmikuuta 2019Vastaa

    Onko olemassa tapaa asettaa rajoitus sille, kuinka monta kertaa voit kirjoittaa "("? Kuten tässä esimerkissä: ((((098)-098-0987 , voit kirjoittaa niin monta sulkumerkkiä kuin haluat ja ohjelma sanoisi, että tämä on kelvollinen lomake puhelinnumerolle.

    • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (8)

      Manish Vachharajani

      19. helmikuuta 2019Vastaa

      Voit yhdistää tämän joko \(* tarkoittaa nollaa tai useampaa, \(+ yhtä tai useampaa, ja voit yleensä käyttää \({2,4}) vastaamaan 2-4 sulkeita.

    • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (9)

      Manish Vachharajani

      19. helmikuuta 2019Vastaa

      Unohdin kuitenkin huomauttaa, että säännölliset lausekkeet eivät yleensä voi vastata muuttuvaa määrää avaavia ja sulkevia sulkuja. Toisin sanoen et voi sanoa, että alkusulkuja pitäisi olla 1–5 ja sitten vastaava määrä sulkevia sulkeita. Tällainen rajoitus ei kuulu niin kutsuttujen säännöllisten kielten soveltamisalaan, joita säännölliset lausekkeet toteuttavat.

  • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (10)

    Dexter Jones

    4. maaliskuuta 2019Vastaa

    voitko käyttää () vastineena säännöllisissä lausekkeissa eli merkkijonomalli = @"{|}\\[|]"

    • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (11)

      Manish Vachharajani

      4. maaliskuuta 2019Vastaa

      Jos haluat löytää kirjaimellisen sulkumerkin, voit välttää sen a\. Niin,\(+vastaa yhtä tai useampaa vasenta sulkua. Voit siis kohdistaa minkä tahansa kiinteän päiden lukumäärän tällä tavalla.\(\(x+\)\)tulee yhteen((xxx)). Et voi sanoa, että minulla on mielivaltainen määrä yläpäätä, mutta ne vastaavat vain, jos vasen ja oikea ovat tasapainossa.

  • 3 Kinds of Parentheses: Are you a RegEx Master? | Unbounded Systems (12)

    Älykäs

    27. huhtikuuta 2019Vastaa

    Vau! Tämä päästää minut eroon kaikesta sulkujen sekaannuksesta, joka minulla on. Kiitti!

  • Tulla mukaan keskusteluun

    Sähköpostiosoitettasi ei julkaista. Pakolliset kentät on merkitty *

    Jätä vastaus

    Tämä sivusto käyttää Akismetiä roskapostin vähentämiseen.Katso, miten kommenttitietojasi käsitellään.

    Top Articles
    Latest Posts
    Article information

    Author: Chrissy Homenick

    Last Updated: 21/11/2023

    Views: 6533

    Rating: 4.3 / 5 (54 voted)

    Reviews: 93% of readers found this page helpful

    Author information

    Name: Chrissy Homenick

    Birthday: 2001-10-22

    Address: 611 Kuhn Oval, Feltonbury, NY 02783-3818

    Phone: +96619177651654

    Job: Mining Representative

    Hobby: amateur radio, Sculling, Knife making, Gardening, Watching movies, Gunsmithing, Video gaming

    Introduction: My name is Chrissy Homenick, I am a tender, funny, determined, tender, glorious, fancy, enthusiastic person who loves writing and wants to share my knowledge and understanding with you.