Quali caratteri speciali devono essere sfuggiti alle espressioni regolari?


389

Sono stanco di provare sempre a indovinare, se dovessi sfuggire a caratteri speciali come ' ()[]{}|' ecc. Quando uso molte implementazioni di regexps.

È diverso, ad esempio, con Python, sed, grep, awk, Perl, rinomina, Apache, trova e così via. Esiste una serie di regole che dice quando dovrei e quando non dovrei sfuggire a personaggi speciali? Dipende dal tipo di regexp, come PCRE, POSIX o regexps estesi?


4
Buone librerie regex hanno funzioni come " escape()" per consentire l'uso di stringhe arbitrarie come parti regex.
ivan_pozdeev il

2
Puoi usare i correttori di espressioni Regex online come gskinner.com/RegExr (è gratuito). (Digita, quindi passa il mouse sopra il regex digitato)
hexicle

2
Sfuggire a tutti i caratteri non alfanumerici. periodo.
Salman von Abbas,

2
Questa domanda è stata aggiunta alle FAQ sulle espressioni regolari di Stack Overflow , in "Altro".
aliteralmind

1
Questa domanda è stata aggiunta alle FAQ sulle espressioni regolari di Stack Overflow , in "Sequenze di escape".
aliteralmind

Risposte:


365

I personaggi che devi e a cui non devi scappare dipendono dal sapore regex con cui stai lavorando.

Per PCRE e la maggior parte dei cosiddetti sapori compatibili con Perl, sfuggire a queste classi di caratteri esterne:

.^$*+?()[{\|

e queste all'interno delle classi di caratteri:

^-]\

Per le regex estese POSIX (ERE), sfuggire a queste classi di caratteri esterne (uguale a PCRE):

.^$*+?()[{\|

L'evasione di qualsiasi altro carattere è un errore con POSIX ERE.

All'interno delle classi di caratteri, la barra rovesciata è un carattere letterale nelle espressioni regolari POSIX. Non puoi usarlo per sfuggire a nulla. Devi usare il "posizionamento intelligente" se vuoi includere i metacaratteri della classe di caratteri come letterali. Metti ^ ovunque tranne all'inizio, il] all'inizio e il - all'inizio o alla fine della classe di caratteri per abbinarli letteralmente, ad esempio:

[]^-]

Nelle espressioni regolari di base POSIX (BRE), questi sono metacaratteri che è necessario sfuggire per sopprimerne il significato:

.^$*[\

La fuga tra parentesi e parentesi graffe nelle BRE dà loro il significato speciale che le loro versioni senza escape hanno nelle ERE. Alcune implementazioni (ad esempio GNU) danno anche un significato speciale ad altri personaggi quando sono salvati, come \? e +. L'escaping di un carattere diverso da. ^ $ * () {} È normalmente un errore con BREs.

All'interno delle classi di personaggi, i BRE seguono la stessa regola degli ERE.

Se tutto ciò ti fa girare la testa, prendi una copia di RegexBuddy . Nella scheda Crea, fai clic su Inserisci token, quindi su Letterale. RegexBuddy aggiungerà escape se necessario.


1
Mi sembra che tu abbia dimenticato il "/", che deve essere evaso anche fuori da una classe.
Jackthehipster,

11
/non è un metacarattere in nessuno dei sapori delle espressioni regolari che ho citato, quindi la sintassi delle espressioni regolari non richiede la sua fuga. Quando un'espressione regolare è citato come un letterale in un linguaggio di programmazione, quindi la stringa o regex regole di formattazione di quella lingua possono richiedere /o "o 'da sfuggito, e possono anche richiedere `\` essere doppiamente sfuggito.
Jan Goyvaerts,

2
che dire di due punti ":"? Sarà evaso sia all'interno delle classi di personaggi che all'esterno? en.wikipedia.org/wiki/Perl_Compatible_Regular_Expressions dice "PCRE ha regole di escape coerenti: qualsiasi carattere non alfanumerico può essere evitato per significare il suo valore letterale [...]"
nicolallias

4
Potrebbe essere evaso non è la stessa cosa DOVREBBE essere evaso. La sintassi PCRE non richiede mai la fuga di due punti letterali, quindi la fuga di due punti letterali rende solo più difficile la lettura della tua regex.
Jan Goyvaerts,

1
Per ERE non POSIX (quella che uso più spesso perché è ciò che è implementato da Tcl) la fuga di altre cose non genera errori.
slebetman,

61

Modern RegEx Flavors (PCRE)

Include C, C ++, Delphi, EditPad, Java, JavaScript, Perl, PHP (preg), PostgreSQL, PowerGREP, PowerShell, Python, REALbasic, Real Studio, Ruby, TCL, VB.Net, VBScript, wxWidgets, XML Schema, Xojo, XRegExp.
La compatibilità con PCRE può variare

    Dovunque: . ^ $ * + - ? ( ) [ ] { } \ |


Legacy Flavours RegEx (BRE / ERE)

Include awk, ed, egrep, emacs, GNUlib, grep, PHP (ereg), MySQL, Oracle, R, sed.
Il supporto PCRE può essere abilitato nelle versioni successive o utilizzando le estensioni

ERE / awk / egrep / emacs

    Fuori da una classe di caratteri: . ^ $ * + ? ( ) [ { } \ |
    All'interno di una classe di caratteri:^ - [ ]

BRE / ED / grep / sed

    Fuori da una classe di caratteri: . ^ $ * [ \
    All'interno di una classe di caratteri: ^ - [ ]
    per i letterali, non scappare: + ? ( ) { } |
    per il comportamento regex standard, scappa:\+ \? \( \) \{ \} \|


Appunti

  • Se non sei sicuro di un personaggio specifico, può essere sfuggito come \xFF
  • I caratteri alfanumerici non possono essere salvati con una barra rovesciata
  • I simboli arbitrari possono essere salvati con una barra rovesciata in PCRE, ma non BRE / ERE (devono essere salvati solo quando richiesto). Per PCRE ] -ho solo bisogno di scappare all'interno di una classe di caratteri, ma li ho tenuti in un unico elenco per semplicità
  • Le stringhe di espressioni tra virgolette devono avere anche il carattere di escape dei caratteri delle virgolette circostanti e spesso con barre rovesciate raddoppiate (come "(\")(/)(\\.)"contro /(")(\/)(\.)/in JavaScript)
  • A parte gli escape, diverse implementazioni regex possono supportare diversi modificatori, classi di caratteri, ancore, quantificatori e altre caratteristiche. Per maggiori dettagli, controlla regular-expressions.info o usa regex101.com per testare le tue espressioni dal vivo

1
Ci sono molti errori nella tua risposta, incluso ma non limitato a: nessuno dei tuoi gusti "moderni" richiede -o ]deve essere evitato al di fuori delle classi di caratteri. POSIX (BRE / ERE) non ha un carattere di escape all'interno delle classi di caratteri. Il sapore regex in RTL di Delphi è in realtà basato su PCRE. Python, Ruby e XML hanno i loro gusti più vicini a PCRE che a quelli POSIX.
Jan Goyvaerts,

1
@JanGoyvaerts Grazie per la correzione. I sapori che hai citato sono davvero più vicini a PCRE. Per quanto riguarda le fughe, le ho mantenute in quel modo per semplicità; è più facile ricordare solo di fuggire ovunque rispetto a poche eccezioni. Gli utenti esperti sapranno cosa succede se vogliono evitare alcune barre rovesciate. Ad ogni modo, ho aggiornato la mia risposta con alcuni chiarimenti che speriamo affrontino alcune di queste cose.
Beejor

22

Sfortunatamente non esiste davvero un set di codici di escape poiché varia in base alla lingua che si sta utilizzando.

Tuttavia, mantenere una pagina come la pagina Strumenti per le espressioni regolari o questo foglio informativo sulle espressioni regolari può fare molto per aiutarti a filtrare rapidamente le cose.


1
Il cheat sheet dibytebyte è notevolmente semplificato e presenta alcuni errori evidenti. Ad esempio, dice \<e \>sono limiti di parole, che è vero solo (AFAIK) nella libreria regex Boost. Ma altrove si dice <e >sono metacaratteri e devono essere sfuggito (a \<e \>) in base alla lettera, che non vero in ogni sapore
Alan Moore

5

Sfortunatamente, il significato di cose come (e \ (viene scambiato tra le espressioni regolari di stile Emacs e la maggior parte degli altri stili. Quindi, se provi a sfuggire a queste, potresti fare il contrario di ciò che desideri.

Quindi devi davvero sapere quale stile stai cercando di citare.


5

POSIX riconosce molteplici variazioni sulle espressioni regolari - espressioni regolari di base (BRE) ed espressioni regolari estese (ERE). E anche allora, ci sono stranezze a causa delle implementazioni storiche delle utility standardizzate da POSIX.

Non esiste una regola semplice per quando utilizzare quale notazione o anche quale notazione utilizza un determinato comando.

Dai un'occhiata al libro sulle espressioni regolari di Mastering di Jeff Friedl .


4

Davvero, non c'è. ci sono circa mezzo milione di diverse sintassi di regex; sembrano arrivare a Perl, EMACS / GNU e AT&T in generale, ma mi sorprendo sempre.


4

A volte la fuga semplice non è possibile con i personaggi che hai elencato. Ad esempio, l'utilizzo di una barra rovesciata per uscire da una parentesi non funzionerà sul lato sinistro di una stringa di sostituzione in sed, vale a dire

sed -e 's/foo\(bar/something_else/'

Tendo invece a usare semplicemente una semplice definizione di classe di caratteri, quindi l'espressione sopra diventa

sed -e 's/foo[(]bar/something_else/'

che trovo lavori per la maggior parte delle implementazioni regexp.

Le classi di personaggi BTW sono piuttosto componenti regexp alla vaniglia, quindi tendono a funzionare nella maggior parte delle situazioni in cui sono necessari caratteri di escape in regexps.

Modifica: dopo il commento qui sotto, ho pensato di menzionare il fatto che devi anche considerare la differenza tra automi a stati finiti e automi a stati non finiti quando osservi il comportamento della valutazione regexp.

Potresti dare un'occhiata al "libro della palla lucente", noto anche come Effective Perl ( link Amazon disinfettato ), in particolare il capitolo sulle espressioni regolari, per avere un'idea della differenza nei tipi di valutazione del motore regexp.

Non tutto il mondo è un PCRE!

Ad ogni modo, i regexp sono così goffi rispetto a SNOBOL ! Ora che è stato un corso di programmazione interessante! Insieme a quello su Simula .

Ah, le gioie di studiare all'UNSW alla fine degli anni '70! (-:


'sed' è un comando per cui plain '(' non è speciale ma '\ (' è speciale; al contrario, PCRE inverte il senso, quindi '(' è speciale, ma '\ (' non lo è. Questo è esattamente ciò che l'OP chiede.
Jonathan Leffler il

sed è un'utilità * nix che utilizza uno dei set più primitivi di valutazione regexp. PCRE non entra nella situazione che descrivo in quanto coinvolge una diversa classe di automi (in) finiti con il modo in cui valuta le regexps. Penso che il mio suggerimento per il set minimo di sintassi regexp sia ancora valido.
Rob Wells,

1
Su un sistema conforme a POSIX, sed utilizza POSIX BRE, che tratterò nella mia risposta. La versione GNU sul moderno sistema Linux utilizza POSIX BRE con alcune estensioni.
Jan Goyvaerts,


2

Per sapere quando e cosa sfuggire senza tentativi è necessario comprendere con precisione la catena di contesti che la stringa attraversa. Specifica la stringa dal lato più lontano alla sua destinazione finale che è la memoria gestita dal codice di analisi regexp.

Prestare attenzione a come viene elaborata la stringa in memoria: se può essere una stringa semplice all'interno del codice o una stringa immessa nella riga di comando, ma a potrebbe essere una riga di comando interattiva o una riga di comando dichiarata all'interno di un file di script della shell, oppure all'interno di una variabile in memoria menzionata dal codice, o di un argomento (stringa) attraverso un'ulteriore valutazione, o una stringa contenente codice generato dinamicamente con qualsiasi tipo di incapsulamento ...

A ciascuno di questi contesti sono stati assegnati alcuni personaggi con funzionalità speciali.

Quando vuoi passare il personaggio letteralmente senza usare la sua funzione speciale (locale al contesto), allora è il caso che devi scappare, per il prossimo contesto ... che potrebbe aver bisogno di altri caratteri di escape che potrebbero anche essere fuggito nei precedenti contesti. Inoltre ci possono essere cose come la codifica dei caratteri (il più insidioso è utf-8 perché assomiglia a ASCII per i caratteri comuni, ma potrebbe essere facoltativamente interpretato anche dal terminale in base alle sue impostazioni, quindi potrebbe comportarsi diversamente, quindi l'attributo di codifica di HTML / XML, è necessario comprendere esattamente il processo.

Ad esempio, una regexp nella riga di comando che inizia con perl -npe, deve essere trasferita a una serie di chiamate di sistema exec che si collegano come pipe gestite dal file, ciascuna di queste chiamate di sistema exec ha solo un elenco di argomenti che sono stati separati da spazi (non di escape), e possibilmente pipe (|) e reindirizzamento (> N> N> & M), parentesi, espansione interattiva di *e ?,$(())... (tutti questi sono caratteri speciali usati da * sh che potrebbero sembrare interferire con il carattere dell'espressione regolare nel prossimo contesto, ma vengono valutati in ordine: prima della riga di comando. La riga di comando viene letta da un programma come bash / sh / csh / tcsh / zsh, essenzialmente all'interno di virgolette doppie o virgolette singole la fuga è più semplice ma non è necessario citare una stringa nella riga di comando perché per lo più lo spazio deve essere preceduto da barra rovesciata e le virgolette sono non è necessario lasciare disponibile la funzionalità di espansione per i caratteri * e?, ma questo analizza il contesto come all'interno della virgoletta, quindi quando viene valutata la riga di comando il regexp ottenuto in memoria (non come scritto nella riga di comando) riceve lo stesso trattamento sarebbe in un file sorgente. Per regexp esiste un contesto di set di caratteri tra parentesi quadre [],l'espressione regolare perl può essere citata da un ampio set di caratteri non alfa-numerici (ad es. m // o m: / migliore / per / percorso: ...).

Hai ulteriori dettagli sui personaggi in un'altra risposta, che sono molto specifici per il contesto regexp finale. Come ho notato hai detto che trovi la fuga regexp con i tentativi, probabilmente perché un contesto diverso ha un diverso set di caratteri che ha confuso la tua memoria di tentativi (spesso la barra rovesciata è il personaggio usato in quei diversi contesti per sfuggire a un personaggio letterale invece della sua funzione ).



0

Per Ionic (Typescript) devi raddoppiare la barra per scapezzare i personaggi. Ad esempio (questo serve per abbinare alcuni caratteri speciali):

"^(?=.*[\\]\\[!¡\'=ªº\\-\\_ç@#$%^&*(),;\\.?\":{}|<>\+\\/])"

Presta attenzione a questi ] [ - _ . /personaggi. Devono essere tagliati due volte. Se non lo fai, avrai un errore di tipo nel tuo codice.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.