2012-01-03 6 views
58

Digamos que tengo la siguiente cadena:Bash girando cadena de múltiples líneas en un solo separada por comas

something1: +12.0 (some unnecessary trailing data (this must go)) 
something2: +15.5 (some more unnecessary trailing data) 
something4: +9.0 (some other unnecessary data) 
something1: +13.5 (blah blah blah) 

¿Cómo activo que simplemente en

+12.0,+15.5,+9.0,+13.5 

en bash?

+1

posible duplicado de [Conciso y portátil "unirse" en la línea de comandos de Unix] (http://stackoverflow.com/questions/8522851/concise-and-portable-join-on-the-unix-command -line) –

Respuesta

57

Puede utilizar awk y sed:

awk -vORS=, '{ print $2 }' file.txt | sed 's/,$/\n/' 

O si desea utilizar una tubería:

echo "data" | awk -vORS=, '{ print $2 }' | sed 's/,$/\n/' 

Para descomponerlo:

  • awk es grande en el manejo de datos desglosados ​​en los campos
  • -vORS=, establece el "separador de registro de salida" a ,, que es lo que quería
  • { print $2 } dice awk para imprimir el segundo campo para cada registro (línea)
  • file.txt es el nombre del archivo
  • sed simplemente se deshace de la , detrás y lo convierte en una nueva línea (si no desea la nueva línea, puede hacerlo s/,$//)
+0

awk: inválida -v opción :( – Gevorg

+3

Agregar un espacio entre -v y ORS =, (para mí, en osx) –

+0

¿Cómo hacer el mismo comando para obtener tuberías separadas? 'Awk -v ORS = | '{print $ 1 } 'DCMC.rtf | sed' s /, $/\ n/''recibo un error – Techiee

8
$ awk -v ORS=, '{print $2}' data.txt | sed 's/,$//' 
+12.0,+15.5,+9.0,+13.5 

$ cat data.txt | tr -s ' ' | cut -d ' ' -f 2 | tr '\n' ',' | sed 's/,$//' 
+12.0,+15.5,+9.0,+13.5 
+0

aplausos, ¿qué pasa si la entrada a awk fue a través de la entrada estándar (simplemente ponga 'function | awk ... 'en tu ejemplo? –

+0

Sí, eso creo. – kev

0

Con Perl:

[email protected] ~ $ perl -ne 'push @l, (split(/\s+/))[1]; END { print join(",", @l) . "\n" }' <<EOF 
something1: +12.0 (some unnecessary trailing data (this must go)) 
something2: +15.5 (some more unnecessary trailing data) 
something4: +9.0 (some other unnecessary data) 
something1: +13.5 (blah blah blah) 
EOF 

+12.0,+15.5,+9.0,+13.5 
0

También puede hacerlo con dos llamadas de sed:

$ cat file.txt 
something1: +12.0 (some unnecessary trailing data (this must go)) 
something2: +15.5 (some more unnecessary trailing data) 
something4: +9.0 (some other unnecessary data) 
something1: +13.5 (blah blah blah) 
$ sed 's/^[^:]*: *\([+0-9.]\+\) .*/\1/' file.txt | sed -e :a -e '$!N; s/\n/,/; ta' 
+12.0,+15.5,+9.0,+13.5 

Primera llamada SED elimina los datos sin interés, y el segundo unirse a todas las líneas.

7

Esto debería funcionar también

awk '{print $2}' file | sed ':a;{N;s/\n/,/};ba' 
4

Esto podría funcionar para usted:

cut -d' ' -f5 file | paste -d',' -s 
+12.0,+15.5,+9.0,+13.5 

o

sed '/^.*\(+[^ ]*\).*/{s//\1/;H};${x;s/\n/,/g;s/.//p};d' file 
+12.0,+15.5,+9.0,+13.5 
0

También puede imprimir la siguiente manera:

Sólo AWK: usando printf

bash-3.2$ cat sample.log 
something1: +12.0 (some unnecessary trailing data (this must go)) 
something2: +15.5 (some more unnecessary trailing data) 
something4: +9.0 (some other unnecessary data) 
something1: +13.5 (blah blah blah) 

bash-3.2$ awk ' { if($2 != "") { if(NR==1) { printf $2 } else { printf "," $2 } } }' sample.log 
+12.0,+15.5,+9.0,+13.5 
93

limpio y sencillo:

awk '{print $2}' < file.txt | paste -s -d, - 
+1

Funcionó muy bien para mis necesidades. Olvidé el comando pegar. –

+2

Esta es la mejor respuesta aquí, y obviamente la forma correcta de hacerlo – forresthopkinsa

+0

¿Cómo puedo citar cada valor con comillas simple/doble? – Hussain

2

intente esto:

sedSelectNumbers='s".* \(+[0-9]*[.][0-9]*\) .*"\1,"' 
sedClearLastComma='s"\(.*\),$"\1"' 
cat file.txt |sed "$sedSelectNumbers" |tr -d "\n" |sed "$sedClearLastComma" 

lo bueno es la parte más fácil de borrar nueva línea "\ n" caracteres!

EDITAR: otra gran manera de unir líneas en una sola línea con sed es esto: |sed ':a;N;$!ba;s/\n/ /g' obtenido de here.

+0

¡Que EDITAR es increíble - +1! – JoeG

0

Otra solución Perl, similar a awk de Dan Fego:

perl -ane 'print "$F[1],"' file.txt | sed 's/,$/\n/' 

-a dice Perl para dividir la línea de entrada en la matriz @F, que se indexa a partir de 0.

1

Puede utilizar grep :

grep -o "+\S\+" in.txt | tr '\n' ',' 

que encuentra la cadena que comienza con +, seguido de cualquier cadena \S\+, a continuación, convertir nuevos caracteres de línea en comas. Esto debería ser bastante rápido para archivos grandes.

0

Una solución pura escrito en Bash:

#!/bin/bash 

sometext="something1: +12.0 (some unnecessary trailing data (this must go)) 
something2: +15.5 (some more unnecessary trailing data) 
something4: +9.0 (some other unnecessary data) 
something1: +13.5 (blah blah blah)" 

a=() 
while read -r a1 a2 a3; do 
    # we can add some code here to check valid values or modify them 
    a+=("${a2}") 
done <<< "${sometext}" 
# between parenthesis to modify IFS for the current statement only 
(IFS=',' ; printf '%s: %s\n' "Result" "${a[*]}") 

Resultado: + 12,0, 15,5 +, + 9,0, + 13,5

3
cat data.txt | xargs | sed -e 's/ /, /g' 
1

No ve esta solución sencilla con awk

awk 'b{b=b","}{b=b$2}END{print b}' infile 
0

awk one liner

$ awk '{printf (NR>1?",":"") $2}' file 

+12.0,+15.5,+9.0,+13.5 
Cuestiones relacionadas