Como imprimir a primeira coluna da próxima linha na linha atual?

8

Eu tenho algum arquivo como este:

abc 123    
abc 789  
bcd 456  
acb 135

Gostaria de imprimir a primeira coluna da próxima linha na linha atual.

Saída desejada:

abc  123 abc  
abc 789 bcd  
bcd 456 acb  
acb 135 

Eu prefiro usar awk.

user2905046
fonte

Respostas:

16

Memorize a linha anterior:

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

Isso processa a entrada da seguinte maneira:

  • se a linha atual for a segunda ou maior, imprima a linha anterior (armazenada em prev, consulte a próxima etapa) e o primeiro campo da linha atual, separado pelo separador do campo de saída (o caractere de espaço por padrão);
  • em todos os casos, armazene a linha atual na prevvariável;
  • no final do arquivo, imprima a linha anterior.
Stephen Kitt
fonte
11

awkAbordagem alternativa :

$ 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

A maneira como isso funciona é simples: a primeira linha é um caso especial - nós a imprimimos sem nova linha e dizemos ao awk para ir para a próxima linha sem executar outros blocos de código. Depois disso, NR == 1{printf "%s", $0;next}é ignorado, mas outras partes fazem o trabalho.

Lembre-se de que, até agora, imprimimos uma string formatada sem novos caracteres de linha. Portanto, o que está sendo feito printf " %s\n%s",$1,$0agora é a primeira palavra impressa (e, como não havia nova linha, ela permanece na mesma linha de saída), a nova linha inserida e a própria linha inteira (mas não termina com o caractere de nova linha) . Assim, a próxima primeira palavra inserida permanecerá na mesma linha. O processo continua até chegarmos ao final do arquivo.

Uma possível melhoria é incluir um END{print ""}bloco para inserir uma nova linha final. Em certos casos em que o arquivo resultante deve ser processado por outros scripts, pode ser desejável.


Enquanto o usuário solicitou o AWK especificamente, a mesma abordagem com a impressão de seqüências de caracteres formatadas pode ser adotada com outros idiomas, por exemplo, Python. Alternativa Python fornecida para aqueles curiosos sobre como isso pode ser implementado em outros 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=" ")

E uso assim:

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

A mesma idéia sobre a nova linha final se aplica aqui.

Sergiy Kolodyazhnyy
fonte
9

Aqui está uma sedmaneira feia apenas por diversão

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

Explicação

  • 2,$ da segunda linha até a última
  • s/[^ ]\+/& &/ dobrar o primeiro conjunto de caracteres que não são espaços em branco
  • ; separa comandos, como no shell
  • s/ /\n/ substitua o primeiro espaço por uma nova linha
  • paste -d ' ' - - junte essa bagunça (acrescente a segunda linha à terceira, a quarta linha à terceira, etc)
Zanna
fonte
1
Como alternativa, você pode usar sedsozinho sem paste:sed -r 'N;s/\n(\w+)/\1&/;P;D' somefile.txt
Digital Trauma
1
Se você escrever sedprogramas para se divertir, então talvez você deve ter um ir para o código-golf ;-)
Trauma Digital
1
@DigitalTrauma ela está no code-golf há 2 meses;) #
Sergiy Kolodyazhnyy
1

Na minha opinião, a abordagem mais simples e legível é:

  1. extrair a primeira coluna ( cut)
  2. exclua a primeira linha da sua coluna extraída ( tail)
  3. cole esta coluna no seu arquivo de origem ( paste)

Exemplo: seu arquivo inpult de amostra:

abc 123    
abc 789  
bcd 456  
acb 135

Em seguida, execute o seguinte comando em um terminal

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

Resultado:

abc 123 abc
abc 789 bcd
bcd 456 acb
acb 135

A estrutura por trás dessa solução difere das respostas fornecidas. Não há necessidade de condições, loops ou expressão regular.

Hölderlin
fonte