¿Cómo puedo "fusionar" patrones en una sola línea?

10

Estoy haciendo grep and sed y obtengo 2 líneas de un archivo que me interesa. ¿Cómo puedo obtener estas líneas en una sola línea que termine con el nuevo carácter de línea?
Ahora estoy obteniendo:

pattern1  
pattern2  

Me gustaría conseguir pattern1 pattern2 \n

Jim
fuente
1
¿Puedes compartir más datos de muestra?
slm
Uso printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'
Valentin Bajrami
Pegar es la herramienta para el trabajo, si tiene la intención de combinar varias líneas de salida en una sola.
slm
alguna herramienta específica? ¿Cómo planeas hacer esto?
Braiam

Respuestas:

7

paste:

{...pipeline...} | paste -d " " - -

Eso dice: "lea una línea de stdin (la primera -), lea otra línea de stdin (la segunda -), luego únalas con un espacio"


una técnica específica de bash:

$ x=$(grep -o pattern. test.txt)
$ echo "$x"
pattern1
pattern2
$ mapfile -t <<< "$x"
$ echo "${MAPFILE[*]}"
pattern1 pattern2

ref: http://www.gnu.org/software/bash/manual/bashref.html#index-mapfile

Glenn Jackman
fuente
¿Qué es - -? ¿Es el comando así?
Jim
@ Jim: sí, eso es correcto. Esos le dicen pastecómo quiere que procese la entrada. 2 a la vez. Agregue más para hacer 3 a la vez. seq 10 | paste -d " " - - .
slm
6

Pondré tres versiones diferentes métodos en una fila

AWK

printf %s\\n pattern1 pattern2 | awk -vRS="\n" -vORS=" " '1; END {print RS}'

SED

printf %s\\n pattern1 pattern2 | sed '$!N;s/\n/ /'

TR

printf %s\\n pattern1 pattern2 | tr '\n' ' '; echo

Y hay muchos más.

Valentin Bajrami
fuente
La trsolución se tragará la nueva línea final, por lo que es posible que desee agregar ; echoa esa
glenn jackman
@glennjackman, ¡ah! Gracias por la pista. Sin embargo, eres libre de modificar la respuesta. Me perdí ese bit!
Valentin Bajrami
2

puede hacerlo usando el script de shell o en la línea de comandos, simplemente coloque la salida del comando en una variable y luego echo:

# x=$(grep -e "pattern1\|pattern2" test)
# printf '%s\n' "$x"
pattern1 pattern2
Nidal
fuente
sin comillas, la variable también está sujeta a la expansión del nombre de archivo, por lo que si tiene caracteres globales (como *o ?) en el resultado, los valores pueden cambiar.
Glenn Jackman
@glennjackman, gracias por mencionar esto, ¿cómo podemos solucionar esto?
Nidal
@Networker al no usar backticks, sino a $()través de printfprintf '%s\n' "$x"
Valentin Bajrami
Esperaría que printf '%s\n' "$x"eso NO elimine la nueva línea "interna".
Glenn Jackman
2

Con sed, puedes hacer esto:

<your previous commands> | sed '{N; s/\n/ /}'
  • N;le dice sedque agregue la siguiente línea en el espacio del patrón, por lo que ahora sedestá trabajando con ambas líneas.
  • s/\n/ / reemplaza el carácter de nueva línea con un espacio, "fusionando" las dos líneas juntas.
Alaa Ali
fuente
2

Una manera simple, salida de tubería a xargs:

$ echo -e 'a\nb' | xargs
a b

Esto solo funciona con una salida pequeña, porque está limitado por el máximo de caracteres por línea de comando. El valor más grande depende del sistema, puede obtener este valor utilizando getconf ARG_MAX.

Cuonglm
fuente
1
( set -f; IFS='
'; printf '%s %s\n' $(grepcmd <input)
) >output

IFS estará encantado de comerlo si lo desea.

mikeserv
fuente
-1

envuelva su sed / grep en backticks

cuando tu comando original era:

grep -i 'foo' mylog.log | sed 's/bar/baz/gi'

su nuevo comando sería:

`grep -i 'foo' mylog.log | sed 's/bar/baz/gi'`

No obtiene los espacios entre líneas, pero siempre puede agregar otro tubo de sed:

 | sed 's/$/ /'
TheRuss
fuente
1
UH no. Eso ejecutará la salida del comando sed.
Glenn Jackman