grep coincide exactamente con dos partes de una cadena

grep coincide exactamente con dos partes de una cadena

¿Cómo uso el comando grep para obtener parte de la cadena como se muestra a continuación?

Cadena:

orange:"orange", red:"apple", purple:"grape", yellow:"banana", green:"watermelon"
red:"strawberries", yellow:"lemon"

Lo que quiero:

red:"apple" yellow:"banana"
red:"strawberries" yellow:"lemon"

He probado esto:

grep -oP '(red:\"[^\"]*).*(yellow:\"[^\"]*)'

Respuesta1

El .*del medio coincide con todo, es decir, con la purple:"grape"pieza. En cambio (suponiendo que quieras seguir con GNU grep), combinaría cada parte por separado con la (foo|bar)construcción "OR".

grep -oP '(red|yellow):\"[^\"]*"'

NB, tuve que agregar el cierre ". Además, no es necesario escapar de ", por lo que puedes usar

grep -oP '(red|yellow):"[^"]*"'

En cualquier caso, esto te da

red:"apple"
yellow:"banana"

luego unir las líneas con espacio entre ellas,

grep -oP '(red|yellow):"[^"]*"' | paste -sd ' ' -

Honestamente, naturalmente lo usaría seden su lugar.

sed -n 's/.*\(red:"[^"]*"\).*\(yellow:"[^"]*"\).*/\1 \2/p'

Respuesta2

grepNormalmente no extrae contenido fuera de línea. Imprime plas líneas que coinciden con una expresión rregular e( globalmente, lleva el nombre del g/re/p edcomando).

Sin embargo, algunas implementaciones como GNU grepque parece que estás usando tienen que -ohacer algo de eso como una extensión.

pcregrepva aún más lejos. Puede -otomar un argumento numérico opcional para generar el contenido de un grupo de captura en lugar de toda la parte coincidente de la línea.

pcregrep -o1 -o2 --om-separator=' ' '(red:"[^"]*").*(yellow:"[^"]*")'

Eso todavía es limitado en lo que puede hacer.

Para extraer información de la línea y realizar más transformaciones, es mejor utilizar un sprocesador de texto como lo han mostrado otros aquí.ed

Respuesta3

De hecho puedes hacerlo con grepcomosugerido por Sparhawk, o con el casi idéntico:

$  echo 'red:"apple", purple:"grape", yellow:"banana"' |      
        grep -oP '(red|yellow):".+?"' | perl -00pe 's/\n/ /'
red:"apple" yellow:"banana"

Personalmente, probablemente lo haría con perl:

$ echo 'red:"apple", purple:"grape", yellow:"banana"' | 
    perl -F, -ane 'map{print if /red|yellow/}@F'
red:"apple" yellow:"banana"

información relacionada