with regular regexp regex sed

regular - sed with regexp



Sed regex y subcadena negaciĆ³n (4)

Este tema puede ser antiguo, pero en aras de la integridad, ¿qué pasa con el operador de negación ! :

Haz que todos los infelices se vuelvan MUY FELICES:

echo -e ''happy/nhappy/nunhappy/nhappy'' | sed ''/^happy/! s/.*/VERY HAPPY/''

Encontré esto aquí: Cómo reemplazar cadenas en líneas que NO comienzan con un patrón determinado

¿Cuál es la sintaxis correcta para encontrar una subcadena (una cadena que está precedida y seguida por cadenas específicas) que no coincide con un patrón específico?

Por ejemplo, quiero tomar todas las subcadenas que comienzan con BEGIN_ , terminar con _END y la subcadena intermedia no es igual a FOO ; y reemplace toda la subcadena con el formato "( subcadena interna )". Lo siguiente coincidiría:

  • BEGIN_bar_END -> (bar)
  • BEGIN_buz_END -> (buz)
  • BEGIN_ihfd8f398IHFf9f39_END -> (ihfd8f398IHFf9f39)

Pero BEGIN_FOO_END no coincidiría.

He jugado con lo siguiente, pero parece que no puedo encontrar la sintaxis correcta:

sed -e ''s/BEGIN_(^FOO)_END/($1)/g'' sed -e ''s/BEGIN_([^FOO])_END/($1)/g'' sed -e ''s/BEGIN_(?!FOO)_END/($1)/g'' sed -e ''s/BEGIN_(!FOO)_END/($1)/g'' sed -e ''s/BEGIN_(FOO)!_END/($1)/g'' sed -e ''s/BEGIN_!(FOO)_END/($1)/g''


Esto podría funcionar para usted:

sed ''h;s/BEGIN_/(.*/)_END/(/1)/;/^(FOO)$/g'' file

Esto solo funciona si solo hay una cadena por línea.

Para múltiples cadenas por línea:

sed ''s/BEGIN_/([^F][^_]*/|F[^O][^_]*/|FO[^O][^_]*/|FOO[^_]/+/)_END//(/1/)/g'' file

O el más fácil de entender:

sed ''s//(BEGIN_/)FOO/(_END/)//1/n/2/g;s/BEGIN_/([^/n_]*/)_END/(/1/)/g;s//n/FOO/g'' file


No hay un operador de negación general en sed , IIRC porque la compilación de expresiones regulares con negación a DFAs toma tiempo exponencial. Puedes solucionar esto con

''/BEGIN_FOO_END/b; s/BEGIN_/(.*/)_END/(/1)/g''

donde /BEGIN_FOO_END/b significa: si encontramos BEGIN_FOO_END , BEGIN_FOO_END (saltamos) al final del script sed .


No sé de una manera bonita, pero siempre podrías hacer esto:

$ cat file BEGIN_FOO_END BEGIN_FrOO_END BEGIN_rFOO_END $ sed ''/BEGIN_FOO_END/ !{s/BEGIN_/([^_]*/)_END/(/1)/}'' file BEGIN_FOO_END (FrOO) (rFOO)