2011-07-08 15 views
7

Quiero usar sed para modificar mi archivo llamado "baz".Cómo usar el comando sed para agregar una cadena antes de una cadena de patrón?

Cuando busco un patrón foo, foo no está al principio o al final de la línea, quiero agregar barra antes de foo, ¿cómo puedo hacerlo usando sed?

Input file named baz: 
blah_foo_blahblahblah 
blah_foo_blahblahblah 
blah_foo_blahblahblah 
blah_foo_blahblahblah 

Output file 
blah_barfoo_blahblahblah 
blah_barfoo_blahblahblah 
blah_barfoo_blahblahblah 
blah_barfoo_blahblahblah 

Respuesta

14

Usted sólo puede usar algo como:

sed 's/foo/barfoo/g' baz 

(el g al final medio global, cada ocurrencia en cada línea en lugar de sólo la primera).

Para una arbitraria patrón (en lugar de fijo) como foo[0-9], podría utilizar grupos de captura de la siguiente manera:

pax$ echo 'xyz fooA abc 
xyz foo5 abc 
xyz fooB abc' | sed 's/\(foo[0-9]\)/bar\1/g' 

xyz fooA abc 
xyz barfoo5 abc 
xyz fooB abc 

Los paréntesis capturar el texto real que coincide con el patrón y la \1 lo utiliza en la sustitución

Puede usar patrones arbitrariamente complejos con este, incluyendo asegurarse de hacer coincidir solo palabras completas. Por ejemplo, sólo cambiando el patrón si está inmediatamente rodeada por un límite de palabra:

pax$ echo 'xyz fooA abc 
xyz foo5 abc foo77 qqq xfoo4 zzz 
xyz fooB abc' | sed 's/\(\bfoo[0-9]\b\)/bar\1/g' 

xyz fooA abc 
xyz barfoo5 abc foo77 qqq xfoo4 zzz 
xyz fooB abc 

En términos de cómo funcionan los grupos de captura, puede utilizar paréntesis para almacenar el texto que coincide con un patrón para su uso posterior en el reemplazo. Los identificadores capturados se basan en los ( caracteres de lectura de izquierda a derecha, por lo que la expresión regular (que he dejado fuera los \ caracteres de escape y rellenan un poco para mayor claridad):

((\S*) (\S*)) 
^^ ^^ ^^ 
| |  | |  | | 
| +--2--+ +--3--+ | 
+---------1---------+ 

cuando se aplica al texto Pax Diablo le daría tres grupos:

\1 = Pax Diablo 
\2 = Pax 
\3 = Diablo 

como se muestra a continuación:

pax$ echo 'Pax Diablo' | sed 's/\(\(\S*\) \(\S*\)\)/[\1] [\2] [\3]/' 
[Pax Diablo] [Pax] [Diablo] 
+0

en realidad quiero agregar una cadena antes de un patrón coincidente, ¿hay alguna manera de hacerlo? –

+1

O incluso 'sed 's/^ foo/bar & /' '. –

+0

bueno, foo no apareció al principio o al final de la línea –

3

Sólo sustituto el inicio de la línea con algo diferente.

sed '/^foo/s/^/bar/' 
+0

la "s" es añadir cadena antes de la coincidencia de patrones ? –

+0

No. Es ** sustituir ** el patrón con el reemplazo. El patrón pasa a ser el comienzo de la línea. –

+0

¿qué tal foo no es el comienzo de la línea? –

0

reemplazar o modificar toda exce "foo" pt al comienzo o al final de la línea, sugeriría reemplazarlos temporalmente al comienzo y al final de la línea con un valor centinela único.

sed 's/^foo/____veryunlikelytoken_bol____/ 
    s/foo$/____veryunlikelytoken_eol____/ 
    s/foo/bar&/g 
    s/^____veryunlikelytoken_bol____/foo/ 
    s/____veryunlikelytoken_eol____$/foo/' 

En sed no hay forma de especificar "no puede igualar aquí". En Perl expresiones regulares y derivados (es decir, lenguas, que tomados de expresiones regulares de Perl, no necesariamente lenguas derivadas del Perl) tiene varias afirmaciones negativas para que pueda hacer algo como

perl -pe 's/(?!^)foo(?!$)/barfoo/g' 
Cuestiones relacionadas