¿Cómo puedo combinar valores de dos columnas?


11

Tengo un archivo en el siguiente formato:

$ cat /tmp/raw
2015-01   5000   1000
2015-02   6000   2000
2015-03   7000   3000

Ahora, lo que quiero es obtener el valor combinado de las columnas 2 y 3 en cada fila para que los resultados sean los siguientes:

2015-01   6000
2015-02   8000
2015-03   9000

Intenté esto pero solo muestra el último valor en el archivo como el valor 2015-03.

Respuestas:


11

Puedes intentar usar awk:

awk '{ print $1, $2 + $3; }' /tmp/raw

El resultado será (supongo que el valor para 2015-03 debería ser 10000):

2015-01 6000
2015-02 8000
2015-03 10000

1
No puedo creer que recibí la respuesta tan rápido: O, nunca recibí una respuesta tan rápida en ningún otro foro :) gracias, el comando funcionó perfectamente :)
Syed Jahanzaib

@SyedJahanzaib, Si esta respuesta resuelve su problema, por favor tome un momento y lo acepta haciendo clic en la marca de verificación a la izquierda. Eso marcará la pregunta como respondida y es la forma en que se agradece en los sitios de Stack Exchange.
terdon

lo siento, olvidé marcar la respuesta. y gracias a todos los demás por su valioso tiempo y sus respuestas, también me ayudaron a aprender a lograr objetivos con un método diferente :)
Syed Jahanzaib

@SyedJahanzaib, aunque obtuve una bonita insignia por esta respuesta, creo que la respuesta de terdon es más precisa y completa.
taliezin

16

Aquí hay algunas maneras:

  1. Otro enfoque awk

    awk '{$2+=$3;}NF--' file
    
  2. Perl

    perl -lane 'print "$F[0] ",$F[1]+$F[2]' file
    

    o

    perl -ape 's/$F[1].*/$F[1]+$F[2]/e' file
    
  3. Shell (mucho más lento / menos eficiente que el anterior)

    while read a b c; do echo "$a $((b + c))"; done < file
    

2
$2+=$3Puede ser más incómodo.
123

@ Usuario112638726 de hecho lo es. Gracias.
terdon

3
También puede usarlo awk '{$2+=$3}NF--'para que no haya todavía un campo en blanco 3 colgando. Aunque esa es solo mi preferencia, y es demasiado similar para publicar como respuesta por sí mismo :)
123

1
@ Usuario112638726 ahora que ni siquiera se me había ocurrido. Mucho más ordenado, gracias!
terdon

Escribí esto para ti. Tenga en cuenta que no solo sedse las arregla para comprender los campos , incluso para definir campos sobre la marcha, y campos con campos , sino que, como aparentemente es el caso, todo el concepto de coincidencia de expresiones regulares de Unix se basa realmente en dividir una cadena en campos de acuerdo a un patrón ! ¿Quien sabe?
mikeserv

5
sed 's/[^ ]* */[&]P/;s//&+pc/3'|dc

...huellas dactilares...

2015-01   6000
2015-02   8000
2015-03   10000

Así que arriba declaro una expresión regular que define una extensión de campo que consiste en una secuencia única de caracteres de *longitud variable que ^no son <espacio> seguida inmediatamente por una secuencia única de caracteres de *longitud variable que son <espacio> . Esta declaración se aplica contra sedel espacio del patrón, que es una cadena delimitada (por defecto) por cada \ncarácter de línea de línea que aparece en la entrada, y que se reemplaza recursivamente (por defecto) con el siguiente para cada aparición de la misma.

La interfaz para esta declaración es doble, y en cada nivel está completamente regulada y especificada por al menos un comité de estándares oficial internacional de IEEE para garantizar la aplicación predecible de la sedsintaxis de comandos. sedLa sintaxis de API , por ejemplo, se aplica en este caso con el comando de /dirección (que siempre es el primer componente de cualquier comando de sustitución) , pero el contenido del mismo es interpretado por una API más básica como un subconjunto del especificado para función en la biblioteca C estándar ./sed s///regcomp()

Puedo hacer estas declaraciones con confianza, porque sedes no sólo un programa, sino, más bien, el compilado ejecutable llamado seden mi Unix máquina es una aplicación de la bien definida, históricamente establecida, y las normas controlado por sed la aplicación de Regular- de mi sistema bibliotecas coincidentes de expresiones.


De la sedespecificación:

La sedutilidad debe admitir los BRE descritos en XBD Basic Regular Expressions ...

... donde encontramos ...

Ambos BREs y EREs son soportados por la interfaz de Expresión Matching Regular en el volumen del sistema Interfaces de POSIX.1-2008 bajo regcomp(), regexec()y las funciones relacionadas.

Una aplicación que llama regcomp()presentará una cadena de patrón y ...

... [l] a regcomp()función compilará la expresión regular contenida en la cadena señalada por el argumento del patrón y colocará los resultados en la estructura preg ...

Para actuar sobre eso, dicha aplicación se referiría a regcomp()la función complementaria de ...

... [l] a regexec()función compara la cadena terminada en cero especificada por la cadena con la expresión regular compilada preg inicializado por una llamada previa a regcomp()...

... regexec()debe completar los elementos de [una] matriz con los desplazamientos de las subcadenas de cadena que corresponden a las \(subexpresiones entre paréntesis \)del patrón ... el patrón en sí mismo cuenta como una subexpresión ...

... [l] a regexec()función debe completar todos los elementos nmatch de pmatch , donde la aplicación proporciona nmatch y pmatch , incluso si algunos elementos de pmatch no corresponden a subexpresiones en el patrón .


Y así cuando lo hago ...

/[^ ]* */

... sedprimero compila la expresión regular y almacena los resultados en la memoria, luego aplica el autómata compilado almacenado allí al contenido de mi espacio de patrones tantas veces como sea necesario para cumplir mi comando. Cada vez que lo hace, el resultado es una matriz de uno o más campos delimitados por nulos como delimitados en los desplazamientos devueltos por regexec().

Y cuando lo haga ...

//

... para indicar que se debe usar la expresión regular definida más recientemente, sedsimplemente puede llamar regexec()nuevamente reutilizando la expresión regular precompilada, pero posiblemente aplicándola esta vez a un argumento de cadena cambiado o aplicando nuevos parámetros nmatch como comando.

Más específicamente aún ...

  • s/[^ ]* */[&]P/
    • reemplace la primera aparición del patrón en el espacio del patrón con un [corchete izquierdo, luego en &sí mismo, luego un ]corchete derecho seguido de un Pcarácter.
  • s//&+pc/3
    • aplique la última expresión regular utilizada nuevamente al espacio de patrón actual y reemplace la 3tercera aparición de patrón en el espacio de patrón con &ella misma seguida de la cadena adjunta +pc.

Y así, para cada línea de sedentrada, escribe en su stdout, dados sus datos de ejemplo:

[2015-01   ]P5000   1000+pc
[2015-02   ]P6000   2000+pc
[2015-03   ]P7000   3000+pc

Esto puede parecer extraño, pero la dccalculadora cita cadenas en su entrada entre corchetes, y el Pcomando imprimirá la parte superior de la pila sin \nagregar una línea e y luego la quitará de la pila de entrada.

Y así, usando la primera línea allí como ejemplo, dchará:

  • [2015-01 ]P
    • Print y pop la parte superior de la pila
  • 5000
    • Empuje el número 5000en la parte superior de la pila y empuje todos los elementos actualmente en la pila (ahora ninguno) hacia abajo en uno.
  • 1000
    • lo mismo, pero esta vez el número 5000 en la parte superior de la pila principal es empujado hacia abajo por uno, y se convierte en el segundo elemento en la pila.
  • +
    • Agregue los dos números superiores en la pila, saque ambos de la pila y empuje la suma hacia la parte superior de la pila.
    • Esto da como resultado una pila que consta solo del número 6000.
    • Este es un error de sintaxis si alguno de los dos elementos superiores de la pila es una [cadena ].
  • p
    • print la parte superior de la pila seguido de un \newline adjunto sin sacarlo de la pila.
  • c
    • cLear la pila

Creo que funciona, pero no puedo analizarlo. En general, está configurando una adición para CC. El primer patrón tiene sentido. Creo que coincide con la fecha y los espacios en blanco finales, pero no entiendo lo que hace poner eso dentro de los corchetes de la clase de caracteres ([&]). Sería genial si deletrearas esto.
Joe

1
@ Joe - ¿algo mejor?
mikeserv

¡Guauu! Eso tiene mucho más sentido (y me muestra un montón de cosas sobre las que necesito aprender más). En particular, nunca había notado el uso de // para reutilizar el patrón actual. Ese es el tipo de cosas que lees y olvidas hasta que te encuentras con un ejemplo real. Muchas gracias. Me hizo reír ver cuánto poder se podía acumular en un comando minúsculo y cuánto tardó en explicarlo.
Joe

@ Joe - bueno ... tal vez me fui un poco por la borda ...
mikeserv
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.