Actualización: En un comentario sobre su pregunta, mencionó que desea limpiar el marcado de wiki y eliminar las secuencias balanceadas de {{
... }}
. Sección 6 del Perl FAQ cubre lo siguiente: Can I use Perl regular expressions to match balanced text?
Considere el siguiente programa:
#! /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.
Su salida:
Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Sed quis
nulla ut dolor fringilla
mollis {{ quis erat.
Para su ejemplo particular, se puede usar
$text =~ s/[^ac]|a(?!c)|(?<!a)c//g;
Es decir, solo borre un a
o c
cuando no sean parte de una secuencia ac
.
En general, esto es complicado de hacer con una expresión regular.
Supongamos que no quiere foo
seguido de espacios en blanco opcionales y luego bar
en $str
. A menudo, es más claro y más fácil de verificar por separado. Por ejemplo:
die "invalid string ($str)"
if $str =~ /^.*foo\s*bar/;
Usted también puede estar interesado en an answer to a similar question, donde escribí
my $nofoo = qr/
( [^f] |
f (?! o) |
fo (?! o \s* bar)
)*
/x;
my $pattern = qr/^ $nofoo bar /x;
Para entender la complicación, leído por Mark How Regexes Work Dominus. El motor compila expresiones regulares en máquinas de estado. Cuando llega el momento de combinar, alimenta la cadena de entrada a la máquina de estados y comprueba si la máquina de estados finaliza en un estado de aceptación.Por lo tanto, para excluir una cadena, debe especificar una máquina que acepte todas las entradas excepto una secuencia particular.
Lo que podría ayudar es un interruptor de expresión regular /v
que crea la máquina de estado como de costumbre pero luego complementa el bit de estado de aceptación para todos los estados. Es difícil decir si esto realmente sería útil en comparación con los controles separados porque una expresión regular /v
aún puede sorprender a las personas, solo que de diferentes maneras.
Si está interesado en los detalles teóricos, vea An Introduction to Formal Languages and Automata por Peter Linz.
Para "cadena simple está (no) contenida en otra cadena", es mejor usar el índice (devuelve -1 si no está contenido). Escribí un analizador de archivos de registro de servidor de correo que primero usó regexp para esas comprobaciones simples, después de cambiar a index() el tiempo de ejecución se redujo a aproximadamente el 25% en comparación con la versión de expresiones regulares. Como índice de bonificación() podría ser más fácil de leer. – dbemerlin
¿Cuál es su objetivo final exactamente? (1) coincide con una cadena que no contiene 'ac' (o alguna otra subcadena), o (2) reemplaza todo en una cadena excepto la subcadena' ac' (por ejemplo, cambia 'abacadac' en' acac')? Sospecho que es el último. –
Para agregar al comentario de @Bart: Proporcione ejemplos de: (1) cadena que desea validar e invalidar O (2) cadena que desea extraer de esta cadena O (3) el resultado de reemplazos en esta cadena. – Kobi