Aggiornamento: In un commento sulla tua domanda, hai menzionato che vuoi pulire il markup wiki e rimuovere le sequenze bilanciate di {{
... }}
. Sezione 6 del Perl FAQ copre questo: Can I use Perl regular expressions to match balanced text?
Si consideri il seguente programma:
#! /usr/bin/perl
use warnings;
use strict;
use Text::Balanced qw/ extract_tagged /;
# for demo only
*ARGV = *DATA;
while (<>) {
if (s/^(.+?)(?=\{\{)//) {
print $1;
my(undef,$after) = extract_tagged $_, "{{" => "}}";
if (defined $after) {
$_ = $after;
redo;
}
}
print;
}
__DATA__
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. {{delete me}} Sed quis
nulla ut dolor {{me too}} fringilla
mollis {{ quis {{ ac }} erat.
La sua uscita:
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Sed quis
nulla ut dolor fringilla
mollis {{ quis erat.
Per esempio particolare, è possibile utilizzare
$text =~ s/[^ac]|a(?!c)|(?<!a)c//g;
Cioè, elimina solo un a
o c
quando non fanno parte di una sequenza ac
.
In generale, questo è difficile da fare con un'espressione regolare.
Dire che non si desidera foo
seguito da spazi bianchi facoltativi e quindi bar
in $str
. Spesso, è più chiaro e più facile da controllare separatamente. Per esempio:
die "invalid string ($str)"
if $str =~ /^.*foo\s*bar/;
Potreste anche essere interessati a an answer to a similar question, dove ho scritto
my $nofoo = qr/
( [^f] |
f (?! o) |
fo (?! o \s* bar)
)*
/x;
my $pattern = qr/^ $nofoo bar /x;
Per capire la complicazione, leggo How Regexes Work da Mark Dominus. Il motore compila le espressioni regolari nelle macchine a stati. Quando è il momento di corrispondere, alimenta la stringa di input alla macchina di stato e controlla se la macchina di stato finisce in uno stato di accettazione.Quindi per escludere una stringa, devi specificare una macchina che accetta tutti gli input eccetto una particolare sequenza.
Ciò che può essere d'aiuto è un commutatore di espressioni regolari /v
che crea la macchina a stati come al solito, ma poi integra il bit di stato di accettazione per tutti gli stati. È difficile dire se questo sarebbe davvero utile rispetto ai controlli separati perché un'espressione regolare /v
può ancora sorprendere le persone, solo in modi diversi.
Se siete interessati ai dettagli teorici, vedere An Introduction to Formal Languages and Automata di Peter Linz.
Per la semplice "stringa è (non) contenuta in un'altra stringa" è preferibile utilizzare l'indice (restituisce -1 se non è contenuto). Ho scritto un parser del file di log del server di posta uno che per primo utilizzava regexp per questi semplici controlli, dopo che sono passato a index() il tempo di esecuzione è stato ridotto a circa il 25% rispetto alla versione regexp. Come indice bonus() potrebbe essere più facile da leggere. – dbemerlin
Qual è il tuo obiettivo finale esattamente? (1) corrisponde a una stringa che non contiene 'ac' (o qualche altra sottostringa), o (2) sostituisce tutto in una stringa tranne la sottostringa' ac' (ad esempio cambia 'abacadac' in' acac')? Sospetto che sia il secondo. –
Per aggiungere al commento di @ Bart: Fornire esempi di: (1) stringa che si desidera convalidare e invalidare la stringa OR (2) da estrarre da questa stringa OPPURE (3) il risultato di sostituzioni in questa stringa. – Kobi