2010-12-14 16 views
6

¿Cómo hago que sed opere en partes específicas de una línea solamente? Y, por el contrario, ¿cómo hago que sed no funcione en partes específicas de una línea?Cómo operar solo en parte de la línea

Ejemplos:

"A a A a (A a) A (a A) a" 

¿Cómo, por ejemplo, reemplazar todos los A s con T s única entre el ( y ) obtener:

"A a A a (T a) A (a T) a" 

Y dada Ejemplo siguiente entrada:

"F f F f (F f) F (f F) f" 

¿Cómo, por ejemplo, reemplazar todos los F s con X s pero no entre el ( y ) a obtener:

"f X f (f F) X X (f F) f "

Realicé búsquedas en Google pero no encontré nada utilizable. Supongo que es una pregunta general sobre sed. El problema es reducible a "plantillas" sed general, espero.

  1. que tiene de operar y A continuación, entre ellos solamente (en todas las instancias en línea dada)
  2. que tiene de y para operar en cualquier otro lugar que entre ellos ...
  3. caso especial cuando desde y hasta son la misma (entre "y" o "foo" y "FOO", etc.) tanto para 1. y 2.

Se debe trabajar con cualquier operación, no sólo la sustitución, sino también con la impresión, etc, al igual imprimiendo todo entre las cadenas "FOO" y "BAR" en cadena.

"1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" 

El resultado será

" d e f i j k " 

Por lo tanto, los ejemplos generales sobre la manera de hacerlo sería muy apreciada. También parece que esta pregunta es bastante común, pero aún no se encuentra un buen howto en Google. También creo que esto sería un gran desafío para responder. Por favor, tampoco proporcione ninguna pista sobre cómo hacerlo usando Perl, AWK o cualquier otra cosa que sed. Esta pregunta es realmente una pregunta solo sed.

+0

Intenté lo mejor. Mi idea era dividir la línea en pedazos por FROM y TO (de alguna manera) y luego "de alguna manera" (todavía no sé cómo) para operar en partes pares o impares solamente o algo por el estilo. Si supiera cómo hacerlo, no preguntaría aquí. Y, es muy probable que mi idea de dividirme sea incorrecta. Es bastante difícil y solía usar sed para tareas simples solo antes. – mjf

Respuesta

1

Dividir y conquistar.

saltos de línea Insertar para separar los segmentos continuación, utilizan los saltos de línea, línea que comienza (^), fin de línea ($) y caracteres delimitadores (paréntesis en este caso) como anclas y bucle. Las nuevas líneas añadidas se eliminan al final.

$ echo "A a A a (A a) A (a A) a" | 
    sed 's/([^)]*)/\n&/g; 
     :a; 
      s/\(\n([^)]*\)A\([^)]*)\)/\1T\2/; 
     ta; 
     s/\n//g' 
A a A a (T a) A (a T) a 
$ echo "F f F f (F f) F (f F) f" | 
    sed 's/(/\n(/g; 
     s/)/)\n/g; 
     :a; 
      s/\([^(]*\)F\([^)]*\(\n\|$\)\)/\1X\2/g; 
     ta; 
     s/\n//g' 
X f X f (F f) X (f F) f 
$ echo "1 2 3 BAR a b c FOO d e f BAR g a h FOO i j k BAR l m n FOO o p q" | 
    sed 's/^/BAR/; 
     s/$/FOO/; 
     s/FOO/&\n/g; 
     s/BAR/\n&/g; 
     s/BAR[^\n]*\n//g; 
     s/[^\n]*FOO\n//g; 
     s/\n//g' 
d e f i j k 
+0

Gracias. Dame algo de tiempo para revisarlo, por favor. – mjf

+0

¿Qué ocurre si quiero reemplazar, por ejemplo, todo AROUND secciones rodeadas por "[" y "]" caracteres como está en la expresión regular? La tarea es similar a transformar una expresión regular normal (donde no es necesario escaparse de todos los caracteres "() [] {} | +?"), Por ejemplo, expresión grep o sed, donde deben escaparse los caracteres especiales. Quiero decir, dado, digamos, la siguiente expresión sed sin haber escapado de los caracteres que deben escaparse en la sintaxis sed porque los convierto en caracteres especiales que me gustaría aplicar en el espacio ALREDEDOR próximo programa sed: "s/\\ ([] [() {} | +?] \\)/\\\ 1/g ". La entrada sería la misma "s/([] [() {} | +?])/\\\ 1/g". – mjf

+0

Mantengo la base de datos de expresiones regulares POSIX BÁSICAS en forma donde "^. [$() | * +? {\" Caracteres necesitan escaparse con "\" para hacerlos "no especiales" (man 7 regex). Necesito un script para transformar estas expresiones regulares en una forma que necesito en un momento dado, digamos la forma grep (1). Entonces lo necesito como, por ejemplo, sed (1) form, o vi editor form, etc. La transformación manual de las expresiones regulares es dolorosa y ahora el db ha crecido a un tamaño bastante grande. Transformar todas las expresiones regulares de forma manual, incluso en un editor tan inteligente como vi, es doloroso. Necesito un guión para esa tarea, que fue mi motivación original para hacer esta pregunta. – mjf

1

Esto podría funcionar para usted (GNU SED):

sed ':a;s/\(([^)]*\)A/\1T/;ta' file # for case 1 

sed ':a;s/\(([^)]*\)F/\1\n/;ta;y/F\n/TF/' file # for case 2 

Para el caso 1 el uso de un bucle de sustituir A 's soportes interiores para T' s.

Para el caso 2 utiliza el mismo que el anterior para cambiar F 's soportes interiores para saltos de línea, luego traducir F' s y saltos de línea a X 's y F' s respectivamente.

Caso 3 es un poco más complicado, pero se puede hacer de 2 comandos sustitutos:

sed -r 's/FOO|BAR/\n&/g;s/[^\n]*(\nBAR[^\n]*)*(\nFOO([^\n]*)\nBAR)?(\nFOO[^\n]*$)?/\3/g' file 

primer prefijo de cada FOO y BAR cadenas con nuevas líneas. A continuación, busque todas las combinaciones de FOO y BAR y mantenga las cadenas entre FOO y BAR. Las nuevas líneas permiten el uso de la clase negativa para simplificar el procedimiento.

Cuestiones relacionadas