¿Cómo depositar solo las líneas que contienen una cadena dada?


13

ENTRADA:

Select ASDF 325 sdfg sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg sdfg 4456 sdrg

SALIDA:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

En resumen, necesito "sed" "sdfg" a "XXXX".

PERO: solo en líneas que contienen la cadena "Seleccionar ASDF". ¿Cómo puedo hacer esto? (sed, awk, etc.: \)

Respuestas:


19

Puede anteponer la mayoría de los comandos sed con una dirección para limitar las líneas a las que se aplican. Una dirección puede ser un número de línea o una expresión regular delimitada por /.

cat INPUT | sed '/Select ASDF/ s=sdfg=XXXX='

Como mencionó Peter.O, el comando como se escribió anteriormente sustituirá la primera aparición de cualquiera sdfgen la cadena que contiene Select ASDF. Si necesita sustituir la coincidencia exacta sdfgsolo en el caso de que esté en la cuarta columna, debe ir de esta manera:

cat INPUT | sed 's/\(^Select ASDF [^ ]* \)sdfg /\1XXXX /'

1
¿Qué pasa con otro campo que contiene sdfg ? p.ej. 5sdfga
Peter.O

Hmm, en realidad ese tampoco es el problema. He actualizado mi respuesta.
prisa el

¿hay alguna opción para usar: sed '/ Select ASDF / gs = sdfg = XXXX =', así que necesito reemplazar todas las ocurrencias en una línea, no solo la primera? pero sed da error si uso "g"
LanceBaynes

1
Debe escribir gdespués del último =(al final del scomando). Será así:sed '/Select ASDF/ s=sdfg=XXXX=g'
prisa

7

Si solo está cambiando la columna 4 si tiene el valor exacto, entonces usar operadores de igualdad en lugar de expresiones regulares tiene sentido.

awk '$1 == "Select" && $2 == "ASDF" && $4 == "sdfg" {$4 = "XXXX"} {print}'

1
¡Rápido! .. comparándolo, para 1 millón de líneas, con el awk de Birei y el sed posicional de Rush : 0m1.580s vs. 0m3.792s vs. 0m6.740s
Peter.O

1

Utilizando GNU awk:

awk '
    BEGIN { IGNORECASE = 1 } 
    /^select asdf/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

Salida:

Select ASDF 325 XXXX sdflk lk
Select TRG 46sdg rasdftz fsgs 45
Select ASDF 6ffg XXXX 4456 sdrg

ACTUALIZACIÓN : Evite IGNORECASEpara un no GNU awk, y coincida con mayúsculas y minúsculas. Gracias a jw013 , quien señaló ese detalle:

awk ' 
    /^Select ASDF/ { 
        sub( /\<sdfg\>/, "XXXX", $0 ) 
    } 
    { print }
' infile

1
Debe mencionar que IGNORECASEes una extensión awk/ GNU gawk.
jw013

1
@ jw013: Gracias. Respuesta actualizada con su sugerencia.
Birei

44
IGNORECASE está mal en este caso, ya sea GNU o G'not .. El criterio en la pregunta es explícitamente para mayúsculasASDF
Peter.O
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.