with - Come negare una parola specifica in regex?



regex tutorial (7)

So che posso annullare il gruppo di caratteri come in [^bar] ma ho bisogno di un'espressione regolare in cui la negazione si applica alla parola specifica - quindi nel mio esempio come faccio a negare una "bar" effettiva e non "any chars in bar" ?

https://code.i-harness.com


A meno che le prestazioni non siano di estrema importanza, spesso è più semplice eseguire i risultati con un secondo passaggio, ignorando quelli che corrispondono alle parole che si desidera negare.

Le espressioni regolari di solito indicano che si sta eseguendo script o qualche tipo di attività a bassa prestazione, quindi è consigliabile trovare una soluzione facile da leggere, facile da comprendere e di facile manutenzione.


Avevo una lista di nomi di file, e volevo escluderne alcuni, con questo tipo di comportamento (Ruby):

files = [
  'mydir/states.rb',      # don't match these
  'countries.rb',
  'mydir/states_bkp.rb',  # match these
  'mydir/city_states.rb' 
]
excluded = ['states', 'countries']

# set my_rgx here

result = WankyAPI.filter(files, my_rgx)  # I didn't write WankyAPI...
assert result == ['mydir/city_states.rb', 'mydir/states_bkp.rb']

Ecco la mia soluzione:

excluded_rgx = excluded.map{|e| e+'\.'}.join('|')
my_rgx = /(^|\/)((?!#{excluded_rgx})[^\.\/]*)\.rb$/

Le mie ipotesi per questa applicazione:

  • La stringa da escludere si trova all'inizio dell'input o immediatamente dopo una barra.
  • Le stringhe consentite terminano con .rb .
  • I nomi file consentiti non hanno un . carattere prima del .rb .

La risposta accettata è buona, ma in realtà è un aggiramento per la mancanza di un operatore di negazione di sottoespressione semplice nelle espressioni regex. Questo è il motivo per cui grep --invert-match esce. Quindi in * nix, puoi ottenere il risultato desiderato usando pipe e una seconda regex.

grep 'something I want' | grep --invert-match 'but not these ones'

Ancora una soluzione, ma forse più facile da ricordare.


La seguente regex farà ciò che vuoi (purché siano supportati lookbehind e lookaheads negativi), facendo corrispondere le cose correttamente; l'unico problema è che combina i singoli caratteri (ad esempio, ogni corrispondenza è un singolo carattere piuttosto che tutti i caratteri tra due "barre" consecutive), con il rischio potenziale di un sovraccarico elevato se si lavora con stringhe molto lunghe.

b(?!ar)|(?<!b)a|a(?!r)|(?<!ba)r|[^bar]

Potresti utilizzare un look-ahead o look-behind negativo :

^(?!.*?bar).*
^(.(?<!bar))*?$

O usa solo le basi:

^(?:[^b]+|b(?:$|[^a]|a(?:$|[^r])))*$

Questi corrispondono a tutto ciò che non contiene bar .


Spero di completare la risposta

Poiché Chris ha specificato Regex Tutorial è la migliore risorsa per l'apprendimento delle espressioni regolari.

Tuttavia, ha davvero consumato tempo per leggere.

Faccio un cheatsheet per la convenienza mnemonica.
[] , () , {} leader di ogni classe che è facile da ricordare.

Regex =
{'single_character': ['[]', '.', {'negate':'^'}],
 'capturing_group' : ['()', '|', '\\', 'backreferences and named group'],
 'repetition'      : ['{}', '*', '+', '?', 'greedy v.s. lazy'],
 'anchor'          : ['^', '\b', '$'],
 'non_printable'   : ['\n', '\t', '\r', '\f', '\v'],
 'shorthand'       : ['\d', '\w', '\s'],
 }

Soluzione:

^(?!.*STRING1|.*STRING2|.*STRING3).*$

xxxxxx OK

xxxSTRING1xxx KO (è se è desiderato)

xxxSTRING2xxx KO (è se è desiderato)

xxxSTRING3xxx KO (è se è desiderato)





regex