¿Cómo imprimir la primera columna de la línea siguiente en la línea actual?

8

Tengo un archivo como este:

abc 123    
abc 789  
bcd 456  
acb 135

Me gustaría imprimir la primera columna de la siguiente línea en la línea actual.

Salida deseada:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

Prefiero usar awk.

user2905046
fuente

Respuestas:

16

Memoriza la línea anterior:

awk 'NR > 1 { print prev, $1 } { prev = $0 } END { print prev }'

Esto procesa la entrada de la siguiente manera:

  • si la línea actual es la segunda o mayor, imprima la línea anterior (almacenada prev, vea el siguiente paso) y el primer campo de la línea actual, separados por el separador de campo de salida (el carácter de espacio por defecto);
  • en todos los casos, almacene la línea actual en la prevvariable;
  • Al final del archivo, imprima la línea anterior.
Stephen Kitt
fuente
11

awkEnfoque alternativo :

$ awk 'NR == 1{printf "%s", $0;next}{printf " %s\n%s", $1,$0}' input.txt                                    
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

La forma en que esto funciona es simple: la primera línea es un caso especial: la imprimimos sin nueva línea y le decimos a awk que pase a la siguiente línea sin ejecutar otros bloques de código. Después de eso, NR == 1{printf "%s", $0;next}se omite, pero otras partes hacen el trabajo.

Recuerde que hasta ahora imprimimos una cadena formateada sin un nuevo carácter de línea. Por lo tanto, lo que se está haciendo printf " %s\n%s",$1,$0ahora es la primera palabra impresa (y como no había nueva línea, permanece en la misma línea de salida), nueva línea insertada y luego toda la línea en sí (pero no termina con el carácter de nueva línea) . Por lo tanto, la siguiente primera palabra insertada permanecerá en la misma línea. El proceso continúa hasta que llegamos al final del archivo.

La posible mejora es incluir el END{print ""}bloque para insertar la nueva línea final. En ciertos casos donde el archivo resultante será procesado por otros scripts, puede ser deseable.


Si bien el usuario solicitó AWK específicamente, el mismo enfoque con la impresión de cadenas formateadas se puede tomar con otros idiomas, por ejemplo Python. La alternativa de Python proporciona a aquellos curiosos acerca de cómo se puede implementar esto en otros idiomas:

#!/usr/bin/env python
from __future__ import print_function
import sys

old = None
for index,line in enumerate(sys.stdin):
    if index == 0:
        print(line.strip(),end=" ")
        continue
    words = line.strip().split()
    print(words[0] + "\n" + line.strip(),end=" ")

Y uso así:

$ ./append_first.py < input.txt                            
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

La misma idea sobre la nueva línea final se aplica aquí.

Sergiy Kolodyazhnyy
fuente
9

Aquí hay una sedmanera fea solo por diversión

sed '2,$ s/[^ ]\+/& &/; 2,$ s/ /\n/' file | paste -d ' ' - -
abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135 

Explicación

  • 2,$ desde la segunda línea hasta la última
  • s/[^ ]\+/& &/ duplicar el primer conjunto de caracteres que no son espacios en blanco
  • ; separa comandos, como en el shell
  • s/ /\n/ reemplazar el primer espacio con una nueva línea
  • paste -d ' ' - - pegue este desastre (agregue la segunda línea al tercero, la cuarta línea al tercero, etc.)
Zanna
fuente
1
Alternativamente, podría usarlo sedsolo sin paste:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt
Digital Trauma
1
Si escribes sedprogramas por diversión, entonces quizás deberías probar code-golf ;-)
Digital Trauma
1
@DigitalTrauma ha estado en code-golf durante 2 meses;)
Sergiy Kolodyazhnyy
1

En mi opinión, el enfoque más simple y legible es:

  1. extraer la primera columna ( cut)
  2. elimine la primera línea de su columna extraída ( tail)
  3. pegue esta columna en su archivo fuente ( paste)

Ejemplo: su archivo inpult de muestra:

abc 123    
abc 789  
bcd 456  
acb 135

Luego ejecute el siguiente comando en una terminal

cut -d' ' -f1 in.txt | tail -n +2 | paste -d' ' file -

Salida:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

La estructura detrás de esta solución difiere de las respuestas dadas. Sin necesidad de condiciones, bucles o expresiones regulares.

Hölderlin
fuente